package com.zmn.oms.zmn.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.channel.common.dro.ChannelDRO;
import com.zmn.base.channel.common.enums.ChannelTypeEnum;
import com.zmn.base.channel.dubbo.interfaces.channel.ChannelListRemoteService;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerLocationDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerLocationRemoteService;
import com.zmn.base.invoice.dubbo.interfaces.manage.InvoiceInfoListRemoteService;
import com.zmn.base.invoice.dubbo.interfaces.manage.InvoiceInfoModifyRemoteService;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.base.pilot.common.dto.pilot.PilotCheckQuery;
import com.zmn.common.dictionary.DictModel;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.map.MapUtils;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.erp.common.exception.ErpBaseException;
import com.zmn.erp.dubbo.utils.DubboConsts;
import com.zmn.manager.redis.RedisManager;
import com.zmn.mcc.common.dto.organize.OrganizeDRO;
import com.zmn.mcc.common.dto.staff.StaffDRO;
import com.zmn.mcc.dubbo.interfaces.organize.OrganizeListRemoteService;
import com.zmn.mcc.dubbo.interfaces.staff.StaffListRemoteService;
import com.zmn.oms.business.interfaces.apply.CancelApplyBService;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.invoice.OrderInvoiceBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.master.OrderMasterBService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.business.interfaces.orderattachment.OrderAttachmentBService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.business.interfaces.remark.OrderRemarkBService;
import com.zmn.oms.business.interfaces.tmall.OrderTmallExtendBService;
import com.zmn.oms.business.interfaces.work.OrderWorkBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.business.interfaces.worktrack.WorkTrackBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dro.conf.channel.ConfChannelWorkOrderTypeDRO;
import com.zmn.oms.common.dro.conf.channel.ConfOrderChannelDRO;
import com.zmn.oms.common.enums.RefundTypeEnum;
import com.zmn.oms.common.enums.WallTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MathUtil;
import com.zmn.oms.model.bo.orderamount.DiscountConditionParamsDIO;
import com.zmn.oms.model.bo.orderamount.OrderAmountDIO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.remind.RemindDTO;
import com.zmn.oms.model.dto.tmall.OrderTmallExtendDTO;
import com.zmn.oms.model.dto.work.masterwork.CompleteDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.invoice.OrderInvoice;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.member.OrderMember;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.orderattachment.OrderAttachmentQuery;
import com.zmn.oms.model.entity.part.OrderPart;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.product.OrderProductExtend;
import com.zmn.oms.model.entity.quotation3.OrderQuotationProcess;
import com.zmn.oms.model.entity.review.OmsOrderReview;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.tag.OrderTag;
import com.zmn.oms.model.entity.tamllextend.OrderTmallExtend;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.warranty.OrderWarranty;
import com.zmn.oms.model.entity.warranty.OrderWarrantyProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.model.vo.remark.OrderRemarkVO;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.model.vo.work.attachmen.OrderWorkAttachmentDetailVO;
import com.zmn.oms.model.vo.work.attachmen.OrderWorkAttachmentVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.invoice.OrderInvoiceService;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.member.OrderMemberService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.orderattachment.OrderAttachmentService;
import com.zmn.oms.services.interfaces.part.OrderPartService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.product.OrderProductExtendService;
import com.zmn.oms.services.interfaces.quotation3.OrderQuotationProcessService;
import com.zmn.oms.services.interfaces.review.OmsOrderReviewService;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import com.zmn.oms.services.interfaces.warranty.OrderWarrantyProductService;
import com.zmn.oms.services.interfaces.warranty.OrderWarrantyService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.redistribute.OrderWorkRedistributeListBService;
import com.zmn.oms.zmn.business.interfaces.statistics.StatOrderBService;
import com.zmn.oms.zmn.business.interfaces.wallquotation.WallQuotationBService;
import com.zmn.oms.zmn.business.interfaces.warranty.ZsOrderWarrantyBService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkGrabBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.masterwork.ZsNormalMasterWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.scm2.dubbo.interfaces.scm.engineer.purchase.EngineerPurchaseModifyRemoteService;
import com.zmn.sp.dubbo.interfaces.manage.SpManageListRemoteService;
import com.zmn.track.common.constant.TrackConfigConsts;
import com.zmn.track.common.constant.TrackConsts;
import com.zmn.track.common.dio.TrackWorkQueryDIO;
import com.zmn.track.dubbo.dto.TrackWorkDRO;
import com.zmn.track.dubbo.dto.TrackWorkQuery;
import com.zmn.track.dubbo.interfaces.trackwork.TrackWorkListRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：啄木鸟平台操作权限
 *
 * @author lujia
 * @date 2018/12/03 14:50
 */
@Service
public class ZsOrderWorkOperatePermissionImpl implements ZsOrderWorkOperatePermissionBService {
    private Logger logger = LoggerFactory.getLogger(ZsOrderWorkOperatePermissionImpl.class);
    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    OrderVisitService orderVisitService;
    @Autowired
    OrderWorkBService orderWorkBService;
    @Autowired
    OrderDetailService orderDetailService;
    @Autowired
    OrderWarrantyService orderWarrantyService;
    @Autowired
    OrderWarrantyProductService orderWarrantyProductService;
    @Autowired
    OrderMemberService orderMemberService;
    @Autowired
    OrderDiscountService orderDiscountService;
    @Autowired
    OrderServiceItemService orderServiceItemService;
    @Autowired
    OrderProductExtendService orderProductExtendService;
    @Autowired
    OrderExtendService orderExtendService;
    @Autowired
    OrderRemarkBService orderRemarkBService;
    @Autowired
    OrderAttachmentService orderAttachmentService;
    @Autowired
    protected OrderInvoiceService orderInvoiceService;
    @Autowired
    protected OrderInvoiceBService orderInvoiceBService;
    @Autowired
    protected ZsMasterWorkBService masterWorkBService;
    @Autowired
    protected ZsNormalMasterWorkBService zsNormalMasterWorkBService;
    @Autowired
    protected OrderTmallExtendBService orderTmallExtendBService;
    @Autowired
    protected OrderDiscountCalcBService orderDiscountCalcBService;
    @Autowired
    protected OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private ZsOrderWarrantyBService zsOrderWarrantyBService;
    @Autowired
    private OrderPartService orderPartService;
    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;
    @Autowired
    private OrderAttachmentBService orderAttachmentBService;
    @Autowired
    private WorkTrackBService workTrackBService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private OrderLogBService orderLogBService;
    @Autowired
    private OrderMasterService orderMasterService;
    @Autowired
    private OrderMasterBService orderMasterBService;
    @Resource
    private RedisManager redisManager;
    @Autowired
    private OrderWorkGrabBService orderWorkGrabBService;
    @Autowired
    private OmsOrderReviewService orderReviewService;
    @Autowired
    OrderWorkListBService orderWorkListBService;
    @Autowired
    private OrderQuotationProcessService orderQuotationProcessService;
    @Autowired
    private OrderStockBService orderStockBService;
    @Autowired
    private StatOrderBService statOrderBService;
    @Resource
    protected BaseCodeService baseCodeService;
    @Resource
    private ConfOrderChannelBService confOrderChannelBService;
    @Resource
    private OrderWorkRedistributeListBService orderWorkRedistributeListBService;
    @Resource
    private WallQuotationBService wallQuotationBService;
    @Autowired
    private CancelApplyBService cancelApplyBService;
    @Autowired
    private OrderTagService orderTagService;
    @Autowired
    private ZsMasterWorkBService zsMasterWorkBService;


    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerPurchaseModifyRemoteService engineerPurchaseModifyRemoteService;
    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ChannelListRemoteService channelListRemoteService;
    @Reference(version = com.zmn.sp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private SpManageListRemoteService spManageListRemoteService;
    @Reference(version = com.zmn.erp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private InvoiceInfoListRemoteService invoiceInfoListRemoteService;
    @org.apache.dubbo.config.annotation.Reference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private TrackWorkListRemoteService trackWorkListRemoteService;
    @org.apache.dubbo.config.annotation.Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    InvoiceInfoModifyRemoteService invoiceInfoModifyRemoteService;
    @Reference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    private StaffListRemoteService staffListRemoteService;
    @Reference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    protected OrganizeListRemoteService organizeListRemoteService;
    //@Reference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    //protected TouchListRemoteService touchListRemoteService;

    @Reference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    protected EngineerLocationRemoteService engineerLocationRemoteService;

    /**
     * 需要收款未支付检查操作类型
     */
    private static final List<Integer> OPERATE_TYPE_LIST = Lists.newArrayList(
            OrderConsts.ORDER_OP_TYPE_UPDATE,
//            OrderConsts.ORDER_OP_TYPE_COMPLETE,
            OrderConsts.ORDER_OP_TYPE_CANCEL,
            OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_BACK,
            OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK,
            OrderConsts.ORDER_OP_TYPE_DISTRIBUTE);

    @Override
    public List<OperatePermissionVO> getOperatePermissionByModuleId(OrderWork orderWork, Integer moduleId, Integer operatorType, Long operatorId) {

        List<OperatePermissionVO> operatePermissionVOList = Lists.newArrayList();
        if (orderWork == null) {
            logger.error("#work#operate#permission order not found ");
            return operatePermissionVOList;
        }

        List<DictModel> operateTypeList = this.getOperateTypeList(orderWork.getPlatWork(), moduleId);

        // 收款未支付检查
        OperatePermissionVO opvo = this.collectionNotPayCheck(orderWork, null, operatorType, operatorId);

        operateTypeList.forEach((operateType) -> {

            // 忽略 录入 操作
            if (Objects.equals(operateType.getKey(), OrderConsts.ORDER_OP_TYPE_INPUT)) {
                return;
            }

            if (!opvo.getCanOperate() && OPERATE_TYPE_LIST.contains(operateType.getKey())) {
                OperatePermissionVO operatePermissionVO = BeanMapper.map(opvo, OperatePermissionVO.class);
                operatePermissionVO.setId(operateType.getKey());
                operatePermissionVO.setName(OrderConsts.getOperateTypeName(operateType.getKey()));
                operatePermissionVOList.add(operatePermissionVO);
                return;
            }

            // 操作权限
            OperatePermissionVO operatePermissionVO = getOperatePermissionByType(orderWork, operateType.getKey(), operatorType, operatorId);
            if (!ObjectUtils.isEmpty(operatePermissionVO)) {
                operatePermissionVOList.add(operatePermissionVO);
            }
        });

        return operatePermissionVOList;
    }

    /**
     * 根据平台标识获取工单操作权限
     */
    private List<DictModel> getOperateTypeList(Integer platWork, Integer moduleId) {

        // 评价操作权限
        if(Objects.equals(moduleId, OrderPremissionConsts.MODULE_ID_ZS_ORDER_COMMENT)){
            return OrderConsts.getCommentOperateTypeList();
        }

        List<DictModel> operateTypeList;

        switch (platWork) {
            case GlobalConsts.PLAT_MARK_YEYX:
                operateTypeList = OrderConsts.getYeyxOperateTypeList();
                break;
            case GlobalConsts.PLAT_MARK_ZMN:
                operateTypeList = OrderConsts.getOperateTypeList();
                break;
            case GlobalConsts.PLAT_MARK_SAAS:
                operateTypeList = OrderConsts.getSaasOperateTypeList();
                break;
            case GlobalConsts.PLAT_MARK_CNHB:
                operateTypeList = OrderConsts.getCnhbOperateTypeList();
                break;
            default:
                operateTypeList = OrderConsts.getOperateTypeList();
                break;
        }

        return operateTypeList;
    }

    @Override
    public OperatePermissionVO getOperatePermission(Long orderId, Long workId, Integer type, Integer operatorType) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        return getOperatePermission(orderWork, type, operatorType);
    }

    /**
     * 工单操作权限
     */
    @Override
    public OperatePermissionVO getOperatePermission(OrderWork order, Integer type, Integer operatorType, Long operatorId) {

        // 收款未支付
        if (OPERATE_TYPE_LIST.contains(type)) {
            OperatePermissionVO operatePermissionVO = this.collectionNotPayCheck(order, type, operatorType, operatorId);
            if (!operatePermissionVO.getCanOperate()) {
                operatePermissionVO.setId(type);
                operatePermissionVO.setName(OrderConsts.getOperateTypeName(type));
                return operatePermissionVO;
            }
        }
        return this.getOperatePermissionByType(order, type, operatorType, operatorId);
    }

    /**
     * 工单操作类型权限
     */
    private OperatePermissionVO getOperatePermissionByType(OrderWork order, Integer type, Integer operatorType, Long operatorId) {
        // 基础过滤
        OperatePermissionVO globalOperatePermission = this.getGlobalOperatePermission(order, type, operatorType, operatorId);
        if (!globalOperatePermission.getCanOperate()) {
            globalOperatePermission.setId(type);
            globalOperatePermission.setName(OrderConsts.getOperateTypeName(type));
            return globalOperatePermission;
        }
        OperatePermissionVO vo = null;
        switch (type) {
            // 确认
            case OrderConsts.ORDER_OP_TYPE_CONFIRM:
                vo = confirmPermission(order);
                break;
            // 派单
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE:
                vo = distributePermission(order);
                break;
            // 派单（新）
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_NEW:
                vo = distributeNewPermission(order);
                break;
            // 派单撤回
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_BACK:
                vo = distributeBackPermission(order, operatorType);
                break;
            // 挂起
            case OrderConsts.ORDER_OP_TYPE_SUSPEND:
                vo = suspendPermission(order);
                break;
            // 服务完成
            case OrderConsts.ORDER_OP_TYPE_SERVICE_COMPLETE:
                vo = serviceCompletePermission(order, operatorType);
                break;
            // 完成
            case OrderConsts.ORDER_OP_TYPE_COMPLETE:
                vo = completePermission(order, operatorId, operatorType);
                break;
            // 收单 - 子公司角色（不包括：子公司老总）
            case OrderConsts.ORDER_OP_TYPE_CHECKOUT:
                vo = checkoutPermission(order);
                break;
            // 收单 - 子公司老总&总部角色
            case OrderConsts.ORDER_OP_TYPE_ADMIN_CHECKOUT:
                vo = adminCheckoutPermission(order);
                break;
            // 取消
            case OrderConsts.ORDER_OP_TYPE_CANCEL:
                vo = cancelPermission(order, operatorType);
                break;
            // 算账 - 子公司角色（不包括：子公司老总）
            case OrderConsts.ORDER_OP_TYPE_ACCOUNT:
                vo = accountPermission(order);
                break;
            // 回访
            case OrderConsts.ORDER_OP_TYPE_REPLY_VISIT:
                vo = replyVisitPermission(order);
                break;
            // 复制
            case OrderConsts.ORDER_OP_TYPE_COPY:
                vo = copyPermission(order);
                break;
            // 返修
            case OrderConsts.ORDER_OP_TYPE_REWORK:
                vo = reworkPermission(order);
                break;
            // 详情
            case OrderConsts.ORDER_OP_TYPE_DETAIL:
                vo = detailPermission(order);
                break;
            // 备注
            case OrderConsts.ORDER_OP_TYPE_REMARK:
                vo = remarkPermission(order);
                break;
            // 多工程师
            case OrderConsts.ORDER_OP_TYPE_MULTI_MASTER:
                vo = multiMasterPermission(order);
                break;
            // 修改
            case OrderConsts.ORDER_OP_TYPE_UPDATE:
                vo = updatePermission(order);
                break;
            // 改渠道
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL:
                vo = updateChannelPermission(order);
                break;
            // 改贴花
            case OrderConsts.ORDER_OP_TYPE_UPDATE_APPLIQUE:
                vo = updateAppliquePermission(order);
                break;
            // 改定金
            case OrderConsts.ORDER_OP_TYPE_UPDATE_PRICE:
                vo = updatePricePermission(order);
                break;
            // 改渠道预收预付款 子公司结算
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
                vo = updateChannelPrePayAmountPermission(order, operatorType);
                break;
/*
            // 改渠道预收预付款 总公司结算
            case OrderConsts.ORDER_OP_TYPE_ADMIN_UPDATE_CHANNEL_PREPAY_AMOUNT:
                vo = adminUpdateChannelPrePayAmountPermission(order);
                break;
*/
            // 优惠
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE:
//            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_TWO:
//            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_THREE:
                vo = discountAndCouponPermission(order);
                break;
            // 优惠券
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_COUPON:
                vo = discountCouponPermission(order);
                break;
            // 特殊优惠
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE:
                vo = discountFreePermission(order);
                break;
            // 服务项
            case OrderConsts.ORDER_OP_TYPE_SERVICE_ITEM:
                vo = serviceitemPermission(order, operatorType);
                break;
            // 核配件
            case OrderConsts.ORDER_OP_TYPE_PART:
                vo = partPermission(order);
                break;
            // 保修信息
            case OrderConsts.ORDER_OP_TYPE_WARRANTY:
                vo = warrantyPermission(order);
                break;
            // 配件报销
            case OrderConsts.ORDER_OP_TYPE_PART_REIMBURSE:
                vo = partReimbursePermission(order);
                break;
            // 开发票
            case OrderConsts.ORDER_OP_TYPE_INVOICE:
                vo = invoicePermission(order);
                break;
            // 推送开票
            case OrderConsts.ORDER_OP_TYPE_INVOICE_REMIND:
                vo = invoiceRemindPermission(order);
                break;
            // 发票反馈
            case OrderConsts.ORDER_OP_TYPE_INVOICE_FEED_BACK:
                vo = invoiceFeedBackPermission(order);
                break;
            // 退款
            case OrderConsts.ORDER_OP_TYPE_REFUND:
                vo = refundPermission(order);
                break;
            // 跟单
//            case OrderConsts.ORDER_OP_TYPE_TRACK:
//                vo = trackPermission(order);
//                break;
            // 跟单(新)
            case OrderConsts.ORDER_OP_TYPE_TRACK_NEW:
                vo = trackPermission(order);
                break;
            // 投诉
            case OrderConsts.ORDER_OP_TYPE_COMPLAINT:
                vo = complaintPermission(order);
                break;
            // 服务异常
            case OrderConsts.ORDER_OP_TYPE_ABNORMAL:
                vo = abnormalPermission(order);
                break;
            // 会员单后台审核
            case OrderConsts.ORDER_OP_TYPE_MEM_PLAT_REVIEW:
                vo = memPlatReviewPermission(order);
                break;
            // 评价备注
            case OrderConsts.ORDER_OP_TYPE_COMMENT_REMARK:
                vo = commentRemarkPermission(order);
                break;
            // 分单
            case OrderConsts.ORDER_OP_TYPE_ASSIGN:
                vo = assignPermission(order);
                break;
            // 分单撤回
            case OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK:
                vo = assignBackPermission(order);
                break;
            // 价格审核
            case OrderConsts.ORDER_OP_TYPE_AMOUNT_REVIEW:
                vo = amountReviewPermission(order);
                break;
            // 邮寄旧件(服务商往厂商邮寄换下来的旧配件）
            case OrderConsts.ORDER_OP_TYPE_OLD_PART_POST:
                vo = oldPartPostPermission(order);
                break;
            // 转单
            case OrderConsts.ORDER_OP_TYPE_TURN:
                vo = turnPermission(order);
                break;
            // 工单照片
            case OrderConsts.ORDER_OP_TYPE_ORDER_PHOTO:
                vo = photoPermission(order);
                break;
            // 签到
            case OrderConsts.ORDER_OP_TYPE_SIGN_IN:
                vo = signInPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_CALL_LOG:
                vo = OperatePermissionVO.success();
                break;
            case OrderConsts.ORDER_OP_TYPE_NONSTANDARD:
                vo = OperatePermissionVO.success();
                break;
            // 快递信息
            case OrderConsts.ORDER_OP_TYPE_EXPRESS:
                vo = orderPostPermission(order);
                break;
            // 新机配件信息
            case OrderConsts.ORDER_OP_TYPE_NEW_MACHINE_PART:
                vo = orderNewMachinePartPermission(order);
                break;
            // 强制派单
            case OrderConsts.ORDER_OP_TYPE_MANDATORY_DISTRIBUTE:
                vo = forceDistributePermission(order);
                break;
            // 更改分配
            case OrderConsts.ORDER_OP_TYPE_CHANGE_ASSIGNMENT:
                vo = changeAssignmentPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_SERVICE_COMPLETE_REVIEW:
                vo = serviceCompleteReviewPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_SPECIAL_ADJUSTMENT:
                vo = specialAdjustment(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_REFUND_VOUCHER:
                vo = refundVoucherPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_MASTER_SHARING:
                vo = masterSharingPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_REMINDER:
                vo = OperatePermissionVO.success();
                break;
            case OrderConsts.ORDER_OP_TYPE_ORDER_TAG:
                vo = markPermission(order);
                break;
            // 多次上门
            case OrderConsts.ORDER_OP_TYPE_MULTIPLE_VISIT:
                vo = multipleVisitPermission(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_COMPENSATE:
                vo = compensateOrderWork(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_COMPENSATE_REVIEW:
                vo = reviewCompensateOrderWork(order);
                break;
            case OrderConsts.ORDER_OP_TYPE_REMIT_VOUCHER:
                vo = remitVoucherOrderWork(order);
                break;
            // 抽查
            case OrderConsts.ORDER_OP_TYPE_ORDER_CHECK:
                vo = OperatePermissionVO.success();
                break;
            // 临时小号
            case OrderConsts.ORDER_OP_TYPE_ORDER_TEMP_XNO:
                vo = tempXnoPermission(order);
                break;
//            // 旧件返厂（厂商指定换下来的配件要不要返厂）
//            case OrderConsts.ORDER_OP_TYPE_OLD_PART_TO_FACTORY:
//                vo = oldPartToFactoryPermission(order);
//                break;
//            // 邮寄配件（厂商给服务商或者用户邮寄配件）
//            case OrderConsts.ORDER_OP_TYPE_PART_POST:
//                vo = partPostPermission(order);
//                break;
//            // 配件撤回（删除没有物流信息的厂商配件）
//            case OrderConsts.ORDER_OP_TYPE_PART_BACK:
//                vo = partBackPermission(order);
//                break;
            case OrderConsts.ORDER_OP_TYPE_MODIFY_PRODUCT:
                vo = OperatePermissionVO.success();
                break;
            case OrderConsts.ORDER_OP_TYPE_MODIFY_QUOTATION:
                vo = OperatePermissionVO.success();
                break;
            default:
                break;
        }

        if (vo != null) {
            vo.setId(type);
            vo.setName(OrderConsts.getOperateTypeName(type));
        }
        return vo;
    }

    /**
     * 工单操作权限
     */
    @Override
    public OperatePermissionVO getOperatePermission(OrderWork order, Integer type, Integer operatorType) {
        return this.getOperatePermission(order, type, operatorType, null);
    }

    @Override
    public OperatePermissionVO getOperatePermission(Long orderId, Long workId, Integer type) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        return getOperatePermission(orderWork, type, null, null);
    }

    @Override
    public OperatePermissionVO getOperatePermission(Long orderId, Long workId, Integer type, Integer operatorType, Long operatorId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        return getOperatePermission(orderWork, type, operatorType, operatorId);
    }

    /**
     * 基础过滤
     * @param order
     * @param type
     * @param operatorId
     * @return
     */
    private OperatePermissionVO getGlobalOperatePermission(OrderWork order, Integer type, Integer operatorType, Long operatorId) {
        // 申请退款后，除REFUND_IGNORE_ORDER_OP_TYPE 定义的能操作，其他功能都不能操作
        if (Objects.equals(order.getRefundReviewStatus(), OrderConsts.REVIEW_STATUS_DOING)) {
            if (!OrderConsts.REFUND_IGNORE_ORDER_OP_TYPE.contains(type)) {
                return OperatePermissionVO.fail("用户申请退款中，不能作此操作");
            }
        }

        // 赔偿单
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            if (!OrderConsts.COMPENSATE_ORDER_OP_TYPES.contains(type)) {
                return OperatePermissionVO.fail("赔偿单，不可操作");
            }
        }

        // 一口价订单退差额过程中过滤
        if (Objects.equals(order.getFinalPrice(), GlobalConsts.YES)) {
            if (order.getStatus() > OrderStatusConsts.WORK_STATUS_VISIT && Objects.equals(order.getPayStatus(), PayConsts.REFUND_STATUS_ING)) {
                if (OrderConsts.ORDER_OP_REFUND_DIFFERENCE_DISABLE_TYPES.contains(type)) {
                    return OperatePermissionVO.fail("订单退差额中，不可操作");
                }
            }
        }
        return OperatePermissionVO.success();
    }

    private OperatePermissionVO compensateOrderWork(OrderWork order) {

        if (!Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("新单 才可操作");
        }

        if (order.getStatus() < OrderStatusConsts.WORK_STATUS_CONFIRM) {
            return OperatePermissionVO.fail("工单已确认 才可操作");
        }

        // 要客不能创建赔偿单
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
        if (Objects.equals(orderDetail.getVvip(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("要客订单不能创建赔偿单");
        }
        return OperatePermissionVO.success();
    }

    private OperatePermissionVO updateCompensateOrderWork(OrderWork orderWork){

        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("非赔偿单，不可操作");
        }

        if (Objects.nonNull(orderWork.getCancelTime()) || Objects.nonNull(orderWork.getCompleteTime())) {
            return OperatePermissionVO.fail("工单已取消或已完成，不可操作");
        }

        OmsOrderReview compensateReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_COMPENSATE);
        if (Objects.isNull(compensateReview)) {
            return OperatePermissionVO.fail("赔偿单未发起审批，不可操作");
        }

        if (!Objects.equals(compensateReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK)) {
            return OperatePermissionVO.fail("赔偿单已审核，不可操作");
        }

        return OperatePermissionVO.success();
    }

    private OperatePermissionVO remitVoucherOrderWork(OrderWork orderWork){
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("非赔偿单，不可操作");
        }

        OmsOrderReview compensateReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_COMPENSATE);
        if (Objects.isNull(compensateReview)) {
            return OperatePermissionVO.fail("赔偿单未发起审核，不可操作");
        }

        if (!Objects.equals(compensateReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_SUCCESS)) {
            return OperatePermissionVO.fail("赔偿单未审核通过，不可操作");
        }

        return OperatePermissionVO.success();
    }

    private OperatePermissionVO reviewCompensateOrderWork(OrderWork orderWork){

        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("非赔偿单，不可操作");
        }

        if (Objects.nonNull(orderWork.getCancelTime()) || Objects.nonNull(orderWork.getCompleteTime())) {
            return OperatePermissionVO.fail("工单已取消或已完成，不可操作");
        }

        OmsOrderReview compensateReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_COMPENSATE);
        if (Objects.isNull(compensateReview)) {
            return OperatePermissionVO.fail("赔偿单未发起审批，不可操作");
        }

        if (!Objects.equals(compensateReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK)) {
            return OperatePermissionVO.fail("赔偿单已审核，不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 派单撤回
     *
     * @param order
     * @return
     */
    private OperatePermissionVO distributeBackPermission(OrderWork order, Integer operatorType) {

        // B 已派单&已领单&已上门-进行中
        List<Integer> supportStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE,
                        OrderStatusConsts.WORK_STATUS_VISIT);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());
        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("已派单&已领单&已上门-进行中 才可操作");
        }

        // C 会员工单：若工程师已经审核通过，则不可撤回
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        // 操作派单撤回不能有进行中的用户、工程师提出的跟单(忽略系统) - 需求提出者：周宗齐
        // 已领单/已上门才校验跟单
        // modify by liuying 修改订单导致的派单撤回 不进行校验
        if (!Objects.equals(GlobalConsts.OPERATE_USER_TYPE_SYSTEM, operatorType)
                && (Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE)
                || Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_VISIT))) {
            TrackWorkQuery query = new TrackWorkQuery();
            query.setOrderId(order.getOrderId());
            query.setWorkId(order.getWorkId());
            query.setNotStatus(TrackConsts.TRACK_STATUS_FINISHED);
            query.setNotTrackContentId(TrackConsts.TRACK_CONTENT_ID_ENGINEER_CANCEL);
            query.setPromoterTypeList(Lists.newArrayList(GlobalConsts.OPERATE_USER_TYPE_USER, GlobalConsts.OPERATE_USER_TYPE_MASTER));

            ResponseDTO<Integer> responseDTO = trackWorkListRemoteService.countTrackByQuery(query);
            if (NumberUtil.isNotNullOrZero(responseDTO.getData()) && responseDTO.getData() > 0) {
                return OperatePermissionVO.fail("工单还有未完结跟单，不可操作");
            }
        }

        // 返修单申请的退款单，如果退款单未完成，则该返修单不能派单撤回
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            OrderWork original = orderWorkService.findOrderWorkByKey(order.getOriginalId(), order.getOriginalId());
            if (NumberUtil.isNotNullOrZero(original.getRefundTargetWorkId())) {
                OrderWork reworkRefund = orderWorkService.findOrderWorkByKey(original.getOrderId(), original.getRefundTargetWorkId());
                if (reworkRefund.getStatus() < OrderStatusConsts.ORDER_STATUS_COMPLETE
                        && Objects.equals(reworkRefund.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                        && Objects.equals(order.getOrderId(), reworkRefund.getRefundWorkId())) {
                    return OperatePermissionVO.fail("源单存在未完结的退款申请，不可操作");
                }
            }
        }

        // 存在已上门子流程，不允许派单撤回
        /*List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterId(order.getOrderId(), order.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            boolean hasVisit = orderVisitList.stream().anyMatch(e -> Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_VISIT));
            if (hasVisit) {
                return OperatePermissionVO.fail("存在已上门子流程，不允许派单撤回");
            }
            boolean hasPay = orderVisitList.stream()
                    .anyMatch(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)
                            && Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE)
                            && (NumberUtil.isNotNullOrZero(e.getOrderPayId())
                            || NumberUtil.isNotNullOrZero(e.getAcceptanceId())));
            if (hasPay) {
                return OperatePermissionVO.fail("存在待支付子流程，不允许派单撤回");
            }
        }*/

        return OperatePermissionVO.success();
    }

    /**
     * 邮寄旧件 （服务商往厂商邮寄换下来的旧配件）
     *
     * @param order
     * @return
     */
    private OperatePermissionVO oldPartPostPermission(OrderWork order) {

        // 保内-进行中 需要返厂
        if (!Objects.equals(com.zmn.consts.GlobalConsts.BIZ_TYPE_F, order.getBizType())) {
            return OperatePermissionVO.fail("保内的订单 才可操作");
        }

        Integer resultStatus = order.getResultStatus();
        if (!Objects.equals(resultStatus, OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("进行中的订单 才可操作");
        }

        // 查询是否需要返厂
        //Long orderId = order.getOrderId();

        // 操作派单撤回不能有进行中的用户、工程师提出的跟单 - 需求提出者：周宗齐
        /*TrackWorkQuery query = new TrackWorkQuery();
        query.setOrderId(order.getOrderId());
        query.setWorkId(order.getWorkId());
        query.setNotStatus(TrackConsts.TRACK_STATUS_FINISHED);
        query.setPromoterTypeList(Lists.newArrayList(GlobalConsts.OPERATE_USER_TYPE_USER, GlobalConsts.OPERATE_USER_TYPE_MASTER));

        ResponseDTO<Integer> responseDTO = trackWorkListRemoteService.countTrackByQuery(query);
        if (NumberUtil.isNotNullOrZero(responseDTO.getData()) && responseDTO.getData() > 0) {
            return OperatePermissionVO.fail("工单还有未完结跟单，不可操作");
        }*/

        return OperatePermissionVO.success();
    }

    /**
     * 转单
     *
     * @param order
     * @return
     */
    public OperatePermissionVO turnPermission(OrderWork order) {

        ConfOrderChannelDRO confOrderChannelDRO = null;
        try {
            confOrderChannelDRO = confOrderChannelBService.getByChannelId(order.getChannelId());
        } catch (OmsBaseException omsBaseException) {
            omsBaseException.printStackTrace();
        }
        if (Objects.nonNull(confOrderChannelDRO) && Objects.equals(confOrderChannelDRO.getOrderTransferType(), GlobalConsts.NO)) {
            return OperatePermissionVO.fail("此类渠道不允许转单");
        }

        // 不是已确认状态
        if (!Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_CONFIRM)) {
            return OperatePermissionVO.fail("工单未确认，不可操作");
        }

        if (!Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可操作");
        }

        // 是否为政企单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_BCUSTOMER)) {
            return OperatePermissionVO.fail("政企单，不可转单");
        }

        // 会员单，工程师审核后不能操作
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        // 返修单或退款单，不可转单
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REWORK)
                || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)
                || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)
        ) {
            return OperatePermissionVO.fail("返修单和退款单和赔偿单，只能由：原单平台服务");
        }

        if (this.isWaitPrePay(order)) {
            return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作转单");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 价格审核
     *
     * @param order
     * @return
     */
    private OperatePermissionVO amountReviewPermission(OrderWork order) {

        // A：金额待审核
        Integer amountReviewStatus = order.getAmountReviewStatus();
        if (!Objects.equals(amountReviewStatus, OrderConsts.REVIEW_STATUS_DOING)) {
            return OperatePermissionVO.fail("已分单-进行中的订单 才可操作");
        }

        // B：已完成-进行中
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_COMPLETE);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());
        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("已完成-进行中的订单 才可操作");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 分单撤回
     *
     * @param order
     * @return
     */
    private OperatePermissionVO assignBackPermission(OrderWork order) {

        if (this.isWaitPrePay(order)) {
            return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
        }

        // 已分单&已派单&已领单&已上门-进行中
        List<Integer> supportStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_ASSIGN, OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                        OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());
        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("工单未分单或已完成或已取消，不可操作");
        }

        // 会员工单，不可分单撤回
        /*if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            return OperatePermissionVO.fail("会员单，不可撤回");
        }*/

        // 会员单，工程师审核后不能操作
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        // 退款单，不可撤回
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND) || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("返修单或退款单或赔偿单，不可撤回");
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作分单撤回");
        }

        // 存在已上门子流程，不允许分单撤回
        /*List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterId(order.getOrderId(), order.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            boolean hasVisit = orderVisitList.stream().anyMatch(e -> Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_VISIT));
            if (hasVisit) {
                return OperatePermissionVO.fail("存在已上门子流程，不允许分单撤回");
            }
            boolean hasPay = orderVisitList.stream()
                    .anyMatch(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)
                            && Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE)
                            && (NumberUtil.isNotNullOrZero(e.getOrderPayId())
                            || NumberUtil.isNotNullOrZero(e.getAcceptanceId())));
            if (hasPay) {
                return OperatePermissionVO.fail("存在待支付子流程，不允许分单撤回");
            }
        }*/

        return OperatePermissionVO.success();
    }

    /**
     * 分单权限
     *
     * @param order
     * @return
     */
    private OperatePermissionVO assignPermission(OrderWork order) {

        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_CONFIRM);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        // 退款单赔偿单，不可操作
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)
                || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("退款单/赔偿单，不可操作");
        }

        // 是否网格化派单
        boolean isGrid = zsDistributeWorkBService.isGridDistribute(order);
        if (isGrid){
            return OperatePermissionVO.fail("该订单属于平台直派，不可操作");
        }

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());
        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("工单未确认，或已分单，不可操作");
        }

        // 会员单，工程师审核后不能派单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作分单");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 评价备注
     *
     * @param orderWork
     * @return
     */
    private OperatePermissionVO commentRemarkPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        Integer platWork = orderWork.getPlatWork();
        if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        }

        if (OrderStatusConsts.WORK_STATUS_COMPLETE > orderWork.getStatus()) {
            return OperatePermissionVO.fail("订单未完成");
        }

        OrderRemarkVO orderRemarkVO = orderRemarkBService
                .findOrderRemarkVO(orderWork.getOrderId(), orderWork.getWorkId(),
                        OrderConsts.ORDER_REMARK_TYPE_COMMENT_REMARK);
        if (orderRemarkVO != null) {
            return OperatePermissionVO.fail("已经备注, 无需重复备注");
        }

        return OperatePermissionVO.success();
    }

    private OperatePermissionVO refundCancelOrUpdatePermission(OrderWork order) {

        Date completeTime = order.getCompleteTime();
        Date cancelTime = order.getCancelTime();
        if (completeTime != null || cancelTime != null) {
            return OperatePermissionVO.fail("退款单已完成或已取消");
        }

        OmsOrderReview refundReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(order.getOrderId(), order.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_REFUND);
        List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkIdsAndTradeType(order.getOrderId(), Lists.newArrayList(order.getWorkId()), PayConsts.PAY_TRADE_TYPE_REFUND);

        if (Objects.isNull(refundReview)) {
            if (CollectionUtil.isNullOrEmpty(orderPays)) {
                return OperatePermissionVO.fail("原路退款申请已提交，不可操作");
            }else {
                OrderPay orderPay = orderPays.get(0);
                if (StringUtil.isNotBlank(orderPay.getRefundImageData())) {
                    return OperatePermissionVO.fail("支付凭证已上传，不可操作");
                }
            }
        }else {
            if (Objects.equals(refundReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_SUCCESS) || Objects.equals(refundReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_FAIL)) {
                return OperatePermissionVO.fail("退款单已审核");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 取消
     *
     * @param order
     * @return
     */
    private OperatePermissionVO cancelPermission(OrderWork order, Integer operatorType) {

        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return this.refundCancelOrUpdatePermission(order);
        }

        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            OrderPay refundPay = orderPayService.getOrderWorkRefundPay(order.getOrderId(), order.getWorkId());
            if (Objects.isNull(refundPay)) {
                return OperatePermissionVO.success();
            }
            return OperatePermissionVO.fail("赔偿单，不可操作");
        }

        /* 1、若工单有：贴花照片和个人形象照片，需有标示结果，才可操作

                - 不可操作提示语：工单有未标记的贴花照片或个人形象照片，不可操作

        2、工单状态：无完成时间或无取消时间，可操作

                - 不可操作提示语：工单已完成或已取消，不可操作

        3、工单：正在支付预付款（包括：啄木鸟预付和渠道预付），不可操作

                - 不可操作提示语：用户还在支付预付款，不可操作

        4、注意：工单已支付定金，也是可以取消*/

        // 1、若工单有：贴花照片和个人形象照片，需有标示结果，才可操作
        // 派单时间在上月，则本月五号之后不校验照片

        // 2、工单状态：无完成时间或无取消时间，可操作
        Date completeTime = order.getCompleteTime();
        Date cancelTime = order.getCancelTime();
        if (completeTime != null || cancelTime != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可操作");
        }

        operatorType = Optional.ofNullable(operatorType).orElse(GlobalConsts.OPERATE_USER_TYPE_STAFF);

        ConfChannelWorkOrderTypeDRO responseDTO = null;
        try {
            responseDTO = confOrderChannelBService.getWorkOrderTypeByChannelId(order.getChannelId());
        } catch (OmsBaseException omsBaseException) {
            omsBaseException.printStackTrace();
        }
        if (Objects.nonNull(responseDTO) && StringUtil.isNotBlank(responseDTO.getWorkOrderCancelType())) {
            String cancelType = responseDTO.getWorkOrderCancelType();

            // 后台操作
            if (!cancelType.contains(String.valueOf(GlobalConsts.LEVEL_1))
                    && Objects.equals(operatorType, GlobalConsts.OPERATE_USER_TYPE_STAFF)) {
                return OperatePermissionVO.fail("该渠道不允许操作取消，请联系渠道运营同学处理");
            }
            // 师傅
            if (!cancelType.contains(String.valueOf(GlobalConsts.LEVEL_2))
                    && Objects.equals(operatorType, GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
                return OperatePermissionVO.fail("该渠道不允许操作取消，请联系渠道运营同学处理");
            }
            // 服务商
            if (!cancelType.contains(String.valueOf(GlobalConsts.LEVEL_3))
                    && Objects.equals(operatorType, GlobalConsts.OPERATE_USER_TYPE_SERVICEPROVIDER)) {
                return OperatePermissionVO.fail("该渠道不允许操作取消，请联系渠道运营同学处理");
            }
        }

        boolean sysOperate = Objects.equals(GlobalConsts.OPERATE_USER_TYPE_SYSTEM, operatorType) || Objects
                .equals(GlobalConsts.OPERATE_USER_TYPE_USER, operatorType) || Objects
                .equals(GlobalConsts.OPERATE_USER_TYPE_CHANNEL, operatorType);

        // 后台操作
        if (!sysOperate) {
            // 特殊渠道限制操作
            /*if (order.getChannelId() != null) {
                int orderChannelId = order.getChannelId().intValue();

                // 58到家c店 和58到家c店独家 需要权限操作
                if ((OrderConsts.CHANNEL_ID_DJ58_CLIENT == orderChannelId
                        || OrderConsts.CHANNEL_ID_DJ58_DUJIA == orderChannelId)
                        && !StaffAdminService.isPermitted("/zs/oms/cancel/58/modify.action")) {
                    return OperatePermissionVO.fail("暂无权限，不可取消");
                }
                // 京东华帝渠道的厂商单不能取消 ......Xiewenbing 2020-05-28
                if (OrderConsts.CHANNEL_ID_JD_HUADI == orderChannelId
                        && order.getInputType() != OrderConsts.ORDER_INPUT_TYPE_MANUAL) {
                    return OperatePermissionVO.fail("该渠道不能操作取消，请引导用户联系商家取消");
                }
                // 到位系列渠道，限制在运营后台不能操作取消   2020-08-05 by lianghailong
                // 因为到位系列渠道，商家主动取消订单会自动赔付30元，为避免赔付，限制在运营后台不能操作取消
                if (DaoweiConsts.CHANNEL_ID_APP == orderChannelId
                        || DaoweiConsts.CHANNEL_ID_DTW == orderChannelId
                        || DaoweiConsts.CHANNEL_ID_KYX == orderChannelId
                        || DaoweiConsts.CHANNEL_ID_ZX == orderChannelId) {
                    return OperatePermissionVO.fail("该渠道不能操作取消，请引导用户操作取消");
                }
            }*/

            Date distributeTime = order.getDistributeTime();
            boolean shouldCheckPhotoStatus = DateUtil.isCurMonthOrBetween1to5Day(distributeTime);
            if (shouldCheckPhotoStatus) {
                // 贴花照片，需有标示结果
                if (!Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
                    OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(order.getOrderId());
                    if (orderExtend != null && (StringUtil.isNotBlank(orderExtend.getAppliqueSrc()) && NumberUtil
                            .isNullOrZero(order.getAppliqueStatus()))) {
                        return OperatePermissionVO.fail("工单有未标记的贴花照片照片，请点击工单照片进行审核");
                    }
                }
            }

            if (this.isWaitPrePay(order)) {
                return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
            }

            Integer prepayStatus = order.getPrepayStatus();
            Integer channelPrepayStatus = order.getChannelPrepayStatus();
            if (Objects.equals(prepayStatus, PayConsts.PAY_STATUS_ING) || Objects
                    .equals(channelPrepayStatus, PayConsts.PAY_STATUS_ING)) {
                return OperatePermissionVO.fail("用户还在支付预付款，不可操作");
            }

            Integer disableDiscard = order.getDisableDiscard();
            if (Objects.equals(disableDiscard, GlobalConsts.YES)) {
                return OperatePermissionVO.fail("禁止弃单状态，不可取消");
            }
        }

        // 处理退款逻辑
        boolean prepayAmountStatus = Objects.nonNull(order.getPrepayAmount()) && Objects
                .equals(order.getPrepayStatus(), PayConsts.PAY_STATUS_DONE);
        boolean depositAmountStatus = Objects.nonNull(order.getDepositAmount()) && Objects
                .equals(order.getDepositStatus(), PayConsts.PAY_STATUS_DONE);
        boolean channelPrepayAmountStatus = Objects.nonNull(order.getChannelPrepayAmount()) && Objects
                .equals(order.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE);
        if (Objects.equals(order.getPlat(), GlobalConsts.PLAT_MARK_CNHB) || Objects
                .equals(order.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB)) {
            if (prepayAmountStatus || depositAmountStatus) {
                return OperatePermissionVO.fail("用户存在已支付定金，不可操作");
            }
        }
        if (channelPrepayAmountStatus && (depositAmountStatus || prepayAmountStatus)) {
            return OperatePermissionVO.fail("用户存在已支付定金，不可操作");
        }

        Integer resultStatus = order.getResultStatus();
        if (!Objects.equals(resultStatus, OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("订单不处于进行中状态，不可操作。");
        }

        // 服务完成 无法取消
        if (order.getStatus() == OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE) {
            return OperatePermissionVO.fail("工单服务完成，不可操作。");
        }

        List<OrderVisit> orderVisitList = orderVisitService.listByOrderId(order.getOrderId());
        boolean waitPay = orderVisitList.stream()
                .anyMatch(e -> Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE)
                        && NumberUtil.isNotNullOrZero(e.getOrderPayId())
                        && !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL));
        if (waitPay) {
            return OperatePermissionVO.fail("用户正在支付，不可操作");
        }

        boolean hasProgressAmount = orderVisitList.stream()
                .anyMatch(e -> Objects.equals(e.getAmountType(), OrderPayConsts.ORDER_PAY_PROGRESS)
                        && Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_DONE)
                        && NumberUtil.isNotNullOrZero(e.getOrderPayId()));
        if (hasProgressAmount) {
            return OperatePermissionVO.fail("已支付进度款，不可操作");
        }

        // 返修单申请的退款单，如果退款单未完成，则该返修单不能派单撤回
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            OrderWork original = orderWorkService.findOrderWorkByKey(order.getOriginalId(), order.getOriginalId());
            if (NumberUtil.isNotNullOrZero(original.getRefundTargetWorkId())) {
                OrderWork reworkRefund = orderWorkService.findOrderWorkByKey(original.getOrderId(), original.getRefundTargetWorkId());
                if (reworkRefund.getStatus() < OrderStatusConsts.ORDER_STATUS_COMPLETE
                        && Objects.equals(reworkRefund.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                        && Objects.equals(order.getOrderId(), reworkRefund.getRefundWorkId())) {
                    return OperatePermissionVO.fail("源单存在未完结的退款申请，不可操作");
                }
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 备注操作权限
     */
    private OperatePermissionVO remarkPermission(OrderWork order) {
        return OperatePermissionVO.success();
    }

    /**
     * 详情操作权限
     */
    private OperatePermissionVO detailPermission(OrderWork order) {
        return OperatePermissionVO.success();
    }

    /**
     * 返修操作权限
     */
    private OperatePermissionVO reworkPermission(OrderWork order) {
        if (order.getCompleteTime() == null) {
            return OperatePermissionVO.fail("工单未完成，不可返修");
        }

        if (!Objects.equals(OrderConsts.ORDER_TYPE_NEW, order.getType())) {
            return OperatePermissionVO.fail("请在新单上建立返修单！");
        }

        // 已算账且已支付
        boolean accountedAndPayed = Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_ACCOUNT)
                && Objects.equals(order.getPayStatus(), PayConsts.PAY_STATUS_DONE);

        // 【当前时间】是否晚于【失败结果时间的一天后】，如果晚了，说明已超过24小时
        boolean failTimeNotIn24 = Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL) &&
                DateUtil.getNow().after(DateUtil.addDays(order.getResultTime(), 1));

        if (accountedAndPayed && failTimeNotIn24) {
            return OperatePermissionVO.fail("超过24小时，不可返修");
        }

/*      // 原单-返修卡是否过期
        OrderWarranty orderWarranty = orderWarrantyService.findByOrderId(order.getOrderId());
        if (orderWarranty != null && Objects.equals(OrderConsts.ORDER_WARRANTY_TYPE_CARD, orderWarranty.getType())) {
            List<OrderWarrantyProduct> orderWarrantyProductList = orderWarrantyProductService.listByOrderId(order
            .getOrderId());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(orderWarrantyProductList)) {
                List<OrderWarrantyProduct> collect = orderWarrantyProductList.stream()
                        .filter(e -> e.getExpiredTime() != null)
                        .collect(Collectors.toList());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(collect)) {
                    boolean validTimeRange = collect.stream().anyMatch(e -> e.getExpiredTime().getTime() > DateUtil
                    .getNow().getTime());
                    if (!validTimeRange) {
                        return OperatePermissionVO.fail("无效返修单号-保修卡已过期");
                    }
                }
            }
        }*/

        // 原单服务商已经禁用了或者已经不服务该区域了，不能创建返修单
        // 20210702 原服务商禁用可以建返修单
        /*if (NumberUtil.isNotNullOrZero(order.getManageCompanyId())) {
            ResponseDTO<SpServProviderDRO> spServProviderDROResponseDTO = spManageListRemoteService.getServProviderById(order.getManageCompanyId());
            SpServProviderDRO spServProviderDRO = spServProviderDROResponseDTO.getData();
            if (Objects.nonNull(spServProviderDRO) && Objects.equals(GlobalConsts.NO, spServProviderDRO.getStatus())) {
                return OperatePermissionVO.fail("服务商已禁用，不可建返修单");
            }
        }*/

        // 原单-原单下有未完成进行中的返修单
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.rangeQuery("status").lt(OrderStatusConsts.WORK_STATUS_COMPLETE))
                .filter(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING))
                .filter(QueryBuilders.termQuery("reworkId", order.getOrderId()));
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 1, Sort.by(Sort.Order.asc("receiveTime"))));
        logger.debug("原单下有未完成进行中的返修单[{}]", searchQuery.getQuery().toString());
        List<EsOrderWork> page = orderWorkEsBService.listPageByQuery(searchQuery);
        if (CollectionUtil.isNotNullOrEmpty(page)) {
            Long doingWorkId =  page.get(0).getId();
            return OperatePermissionVO.fail("原单下有未完成进行中的返修单" + doingWorkId);
        }

        // 原单-返修卡是否过期
        OrderWarranty orderWarranty = orderWarrantyService.findByOrderId(order.getOrderId());
        if (orderWarranty != null && Objects.equals(OrderConsts.ORDER_WARRANTY_TYPE_CARD, orderWarranty.getType())) {
            List<OrderWarrantyProduct> orderWarrantyProductList = orderWarrantyProductService.listByOrderId(order.getOrderId());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(orderWarrantyProductList)) {
                List<OrderWarrantyProduct> collect = orderWarrantyProductList.stream()
                        .filter(e -> e.getExpiredTime() != null)
                        .collect(Collectors.toList());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(collect)) {
                    boolean validTimeRange = collect.stream().anyMatch(e -> e.getExpiredTime().getTime() > DateUtil
                            .getNow().getTime());
                    if (!validTimeRange) {
                        return OperatePermissionVO.fail("工单已过保修期，无法创建返修单");
                    }
                }
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 复制操作权限
     */
    private OperatePermissionVO copyPermission(OrderWork orderWork) {

        // 会员工单不可操作复制
        if (Objects.equals(orderWork.getMember(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("会员工单，不可操作复制");
        }
        // 厂商单，若下单平台和服务平台不一致，不可操作复制
        if (Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY) && !Objects
                .equals(orderWork.getPlatWork(), orderWork.getPlat())) {
            return OperatePermissionVO.fail("厂商单只可在原下单平台操作复制");
        }

        // 等待渠道预支付订单，不可操作
        boolean waitingChannelPrepay = Objects.equals(orderWork.getDisableDiscard(), GlobalConsts.YES);
        if (waitingChannelPrepay) {
            return OperatePermissionVO.fail("工单正在等待渠道支付中，不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 回访操作权限
     */
    private OperatePermissionVO replyVisitPermission(OrderWork order) {

        // A. 已回访 不可再回访
        Date replyVisitTime = order.getReplyVisitTime();
        if (replyVisitTime != null) {
            return OperatePermissionVO.fail("该工单已经回访");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 多工程师操作权限
     */
    private OperatePermissionVO multiMasterPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        //        Integer platWork = orderWork.getPlatWork();
        //        if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
        //            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        //        }

        // 结果-进行中，状态：已领单&已上门&已完成，可操作
        List<Integer> supportStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE,OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        boolean statusSupport = supportStatusList.contains(orderWork.getStatus());

        if (resultStatusSupport && statusSupport) {
            return OperatePermissionVO.success();
        } else {
            return OperatePermissionVO.fail("工单已取消或已完成，收单，算账，不可操作");
        }
    }

    /**
     * 工单修改操作权限
     */
    private OperatePermissionVO updatePermission(OrderWork order) {

        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return this.refundCancelOrUpdatePermission(order);
        }

        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return this.updateCompensateOrderWork(order);
        }

        // 等待渠道预支付订单，不可操作
        boolean waitingChannelPrepay = Objects.equals(order.getDisableDiscard(), GlobalConsts.YES);
        if (waitingChannelPrepay) {
            return OperatePermissionVO.fail("工单正在等待渠道支付中，不可操作");
        }

        // 会员单，工程师审核后不能派单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }
        // 结果-进行中，无：完成时间，可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        Date completeTime = order.getCompleteTime();

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());

        // 服务完成 无法修改
        if (order.getStatus() == OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE) {
            return OperatePermissionVO.fail("工单服务完成，不可操作。");
        }

        if (resultStatusSupport && completeTime == null) {
            return OperatePermissionVO.success();
        } else {
            return OperatePermissionVO.fail("工单已完成或已取消，不可修改");
        }

    }

    /**
     * 修改渠道操作权限
     */
    private OperatePermissionVO updateChannelPermission(OrderWork orderWork) {
        if (!Objects.equals(orderWork.getPlat(), orderWork.getPlatWork())) {
            return OperatePermissionVO.fail("转单工单，不可操作");
        }

        Integer status = orderWork.getStatus();
        Integer sourceType = orderWork.getSourceType();
        if (status == OrderStatusConsts.WORK_STATUS_ACCOUNT) {
            return OperatePermissionVO.fail("工单已算账，不可操作");
        }
        if (status == OrderStatusConsts.WORK_STATUS_CHECKOUT) {
            return OperatePermissionVO.fail("工单已取消，不可操作");
        }
        if (sourceType == 2) {
            return OperatePermissionVO.fail("厂商订单，不可操作");
        }
        // 服务完成不可操作
        if (status == OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE) {
            return OperatePermissionVO.fail("工单服务完成,不可操作");
        }
        // 渠道参数设置为：不允许修改渠道，不可操作
        ConfOrderChannelDRO confOrderChannelDRO = null;
        try {
            confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
        } catch (OmsBaseException omsBaseException) {
            logger.error(omsBaseException.getMessage());
            omsBaseException.printStackTrace();
        }

        if (Objects.nonNull(confOrderChannelDRO)&& Objects.equals(confOrderChannelDRO.getPlatformType(), GlobalConsts.NO)) {
            return OperatePermissionVO.fail("该渠道不允许修改");
        }

        // 会员单，工程师审核后不能操作权限
        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 修改贴花操作权限
     */
    private OperatePermissionVO updateAppliquePermission(OrderWork order) {
        Date accountTime = order.getAccountTime();
        if (accountTime == null) {
            return OperatePermissionVO.fail("未算账不可操作");
        }

        if (!DateUtil.isCurMonthOrBetween1to5Day(accountTime)) {
            return OperatePermissionVO.fail("只可操作本月算账，以及本月1-5号可操作上月算账");
        }

        OrderExtend orderExtend = orderExtendService.findOrderExtendByOrderId(order.getOrderId());
        if (orderExtend == null || StringUtil.isBlank(orderExtend.getAppliqueSrc())) {
            return OperatePermissionVO.fail("暂无贴花照片 不可操作");
        }

        return OperatePermissionVO.success("只可操作本月算账，以及本月1-5号可操作上月算账");
    }

    /**
     * 改定金操作权限
     */
    private OperatePermissionVO updatePricePermission(OrderWork orderWork) {

        // 指定渠道不可修改定金
        if (ChannelConsts.CHANNEL_ID_NO_PAY_DEPOSIT_AMOUNT.contains(orderWork.getChannelId())) {
            return OperatePermissionVO.fail("指定渠道，不可操作");
        }

        // 产品id不能为空
        if (NumberUtil.isNullOrZero(orderWork.getProductId())) {
            return OperatePermissionVO.fail("产品未确定，不可操作");
        }

        // 已支付状态不可修改
        Integer masterPayStatus = orderWork.getMasterPayStatus();
        if (Objects.equals(PayConsts.PAY_STATUS_DONE, masterPayStatus)) {
            return OperatePermissionVO.fail("工单已支付，不可改定金");
        }

        // 定金已支付不可操作
        /*Integer depositStatus = orderWork.getDepositStatus();
        if (Objects.equals(PayConsts.PAY_STATUS_DONE, depositStatus)) {
            return OperatePermissionVO.fail("定金已支付，不可改定金");
        }*/

        // 工单非进行中不可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        if (!resultStatusSupport) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可改定金");
        }

        // 有完成时间不可操作
        Date completeTime = orderWork.getCompleteTime();
        if (completeTime != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可改定金");
        }

        // - 结果：进行中，无：完成时间，并有原价，可：操作
        Integer originalAmount = orderWork.getOriginalAmount();
        if (originalAmount == null) {
            return OperatePermissionVO.fail("先由工程师勾选服务项目，才可改定金");
        }

        // 会员单，工程师审核后不能派单
        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 改预付款操作权限
     */
    private OperatePermissionVO updateChannelPrePayAmountPermission(OrderWork orderWork, Integer operatorType) {
        // 增加校验：返修单、退款单不可操作 - 新加限制
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("返修单或退款单，不可操作");
        }

        // 结果-进行中，无：完成时间，可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        if (!resultStatusSupport) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可操作");
        }

        // 有完成时间不可操作
        Date completeTime = orderWork.getCompleteTime();
        if (completeTime != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可操作");
        }

        try {
            // 判断操作类型是否为渠道，如果不是，则查询渠道配置限制  xiewenbing 2021/01/04
            if (!Objects.equals(operatorType, GlobalConsts.OPERATE_USER_TYPE_CHANNEL)) {
                // 渠道配置限制：配置了允许渠道预收 ，才可操作
                ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(orderWork.getChannelId());
                if (Objects.nonNull(confOrderChannelDRO) && !Objects.equals(confOrderChannelDRO.getPrepayType(), GlobalConsts.YES)) {
                    return OperatePermissionVO.fail("该渠道不可有预付款，不可操作");
                }
            }
        } catch (Exception ex) {
        }

        ResponseDTO<ChannelDRO> channelResponseDTO = channelListRemoteService.getByChannelId(orderWork.getChannelId());
        ChannelDRO channelDRO = channelResponseDTO.getData();
        // 订单类型为：保内单，不可更改 Xiewenbing 2019.11.29
        // 订单类型为：:F类型&渠道类型为厂商和B类型 工单不允许改预付款 wangxiaokun 2020/11/18
        if ((Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)
                && Objects.equals(channelDRO.getChannelType(), ChannelTypeEnum.CJ.getCode()))
                || Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_B)) {
            return OperatePermissionVO.fail("厂商单和工程单不允许修改预付款");
        }

        // 等待渠道预支付订单，不可操作，
        // 排除渠道调用接口操作支付 2020-06-24 by lhl
        if (!Objects.equals(GlobalConsts.OPERATE_USER_TYPE_CHANNEL, operatorType)) {
            boolean waitingChannelPrepay = Objects.equals(orderWork.getDisableDiscard(), GlobalConsts.YES);
            if (waitingChannelPrepay) {
                return OperatePermissionVO.fail("工单正在等待渠道支付中，不可操作");
            }
        }

        // 会员单，工程师审核后不能派单
        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 优惠操作权限
     */
    @Override
    public OperatePermissionVO discountPermission(OrderWork orderWork) {

        // 增加校验：返修单、退款单不可操作 - 新加限制
        // 状态限制，结果：进行中，无：完成时间，可操作
        // 其他限制，工单需有：订单金额
        // 其他限制，工单已有：优惠方式-全免，不可操作
        // 订单已支付 不可优惠
        // 订单服务完成 不可操作
        if (orderWork.getStatus() == OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE) {
            return OperatePermissionVO.fail("工单服务完成，不可操作。");
        }

        // 增加校验：返修单、退款单不可操作 - 新加限制
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("返修单或退款单，不可操作");
        }
        if (ChannelConsts.DISABLE_DISCOUNT_CHANNEL_IDS.contains(orderWork.getChannelId())) {
            return OperatePermissionVO.fail("该渠道暂时不支持人工优惠");
        }

        // A. 状态限制，结果：进行中，无：完成时间，可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        if (!resultStatusSupport || orderWork.getCompleteTime() != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可优惠");
        }

        // B. 其他限制，工单需有：订单金额
        Integer originalAmount = orderWork.getOriginalAmount();
        if (originalAmount == null) {
            return OperatePermissionVO.fail("工单没有原价，不可优惠");
        }

        // C. 工单已有：优惠方式-全免，不可操作
        if (orderWork.getDiscountAmount() != null) {
            List<OrderDiscount> discountList = orderDiscountService.listByOrderId(orderWork.getOrderId());
            boolean hasFreeDiscount = discountList.stream().anyMatch(orderDiscount -> Objects.equals(orderDiscount.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_HQ_COMPANY) ||
                    Objects.equals(orderDiscount.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_SUB_COMPANY)
            );
            if (hasFreeDiscount) {
                return OperatePermissionVO.fail("工单已有优惠：全免，不可再优惠");
            }
        }

        // 订单已支付 不可优惠
        Integer payStatus = orderWork.getPayStatus();
        if (Objects.equals(payStatus, PayConsts.PAY_STATUS_DONE)) {
            return OperatePermissionVO.fail("订单已支付 不可优惠");
        }

        // 会员单，工程师审核后不能操作
        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }

        // 检测优惠是否能使用
        ReCalcOrderAmountDIO calcOrderAmountDIO = new ReCalcOrderAmountDIO();
        calcOrderAmountDIO.setOrderAmountDIO(BeanMapper.map(orderWork, OrderAmountDIO.class));
        calcOrderAmountDIO.setDiscountConditionParamsDIO(BeanMapper.map(orderWork, DiscountConditionParamsDIO.class));
        calcOrderAmountDIO.setOrderDiscountList(NumberUtil.isNotNullOrZero(orderWork.getDiscountAmount()) ? orderDiscountService.listByOrderId(orderWork.getOrderId()) : Collections.emptyList());
        com.zmn.common.dto2.ResponseDTO<Boolean> checkDiscount = orderDiscountCalcBService.checkArtificialDiscount(calcOrderAmountDIO);
        if (!checkDiscount.isSuccess()) {
            return OperatePermissionVO.fail(checkDiscount.getMessage());
        }

        return OperatePermissionVO.success();
    }

    /**
     * 特殊优惠操作权限
     *
     * @author Xiewenbing 2019.11.29
     */
    private OperatePermissionVO discountFreePermission(OrderWork orderWork) {
        if (ChannelConsts.DISABLE_DISCOUNT_CHANNEL_IDS.contains(orderWork.getChannelId())) {
            return OperatePermissionVO.fail("该渠道暂时不支持人工优惠");
        }
        // 返修单、退款单不可操作
        // 状态限制，结果：进行中，无：完成时间，可操作
        // 其他限制，工单需有：订单金额
        // 订单已支付 不可优惠

        // 返修单、退款单不可操作
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("返修单或退款单，不可操作");
        }

        // 状态限制，结果：进行中，无：完成时间，可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        if (!resultStatusSupport || orderWork.getCompleteTime() != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可再优惠");
        }

        // 订单已支付 不可优惠
        Integer payStatus = orderWork.getPayStatus();
        if (Objects.equals(payStatus, PayConsts.PAY_STATUS_DONE)) {
            return OperatePermissionVO.fail("订单已支付 不可优惠");
        }

        if (Objects.equals(GlobalConsts.YES, orderWork.getFullPaymentFlag())) {
            return OperatePermissionVO.fail("工单预付全款，不可操作");
        }

        // 会员单，工程师审核后不可操作
        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }

/*        // 检测优惠是否能使用
        com.zmn.common.dto2.ResponseDTO<Boolean> checkDiscount = orderDiscountCalcBService.checkFreeDiscount(orderWork.getOrderId(), orderWork.getUserId());
        if (!checkDiscount.isSuccess()) {
            return OperatePermissionVO.fail(checkDiscount.getMessage());
        }*/

        // 服务完成 无法操作特殊优惠
        if( Objects.equals(orderWork.getStatus(),OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE)){
            return OperatePermissionVO.fail("工单服务完成，不可修改");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 优惠券操作权限
     */
    private OperatePermissionVO discountCouponPermission(OrderWork orderWork) {

        // 增加校验：退款单不可操作 - 新加限制
        // 状态限制，结果：进行中，无：完成时间，可操作
        // 其他限制，工单需有：订单金额
        // 工单已有其他优惠不可操作
        // 订单已支付 不可优惠
        // 已有渠道预付优惠券不可用

        // 增加校验：退款单不可操作 - 新加限制
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return OperatePermissionVO.fail("退款单，不可操作");
        }

        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("赔偿单，不可操作");
        }

        // A. 状态限制，结果：进行中，无：完成时间，可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());
        if (!resultStatusSupport || orderWork.getCompleteTime() != null) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可优惠");
        }

        // B. 其他限制，工单需有：订单金额
        Integer originalAmount = orderWork.getOriginalAmount();
        if (originalAmount == null) {
            return OperatePermissionVO.fail("工单没有原价，不可优惠");
        }

        if (Objects.equals(GlobalConsts.YES, orderWork.getFullPaymentFlag())) {
            return OperatePermissionVO.fail("工单预付全款，不可操作");
        }

        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (!Objects.isNull(orderMember)) {
            if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (reviewSuccess) {
                return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
            }
        }


        // C. 工单已有其他优惠不可操作
        //        List<OrderDiscount> discountList = orderDiscountService.listByOrderId(orderWork.getOrderId());
        //        if (!CollectionUtils.isEmpty(discountList)) {
        //            return OperatePermissionVO.fail("已有其他优惠");
        //        }

        // D. 已有渠道预付优惠券不可用
        Integer channelPrepayAmount = orderWork.getChannelPrepayAmount();
        if (channelPrepayAmount != null) {
            return OperatePermissionVO.fail("已有渠道预付");
        }

        // 订单已支付 不可优惠
        Integer payStatus = orderWork.getPayStatus();
        if (Objects.equals(payStatus, PayConsts.PAY_STATUS_DONE)) {
            return OperatePermissionVO.fail("订单已支付 不可优惠");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 服务项目操作权限......改价格 Xiewenbing
     * 完成前-限制条件：
     * 1 状态&结果限制：已派单&已领单&已上门- 进行中，可操作；
     * 1.1 不可操作提示语：工单未派单或已取消，不可改价格
     * 2 工单有：后台产品，可操作；
     * 2.1 不可操作提示语：工程师还未确定具体产品，不可操作
     * 3 工单为：新单，可操作；
     * 3.1 不可操作提示语：退款单和返修单，不可改价格
     * 完成后-限制条件：
     * 1 状态&结果限制：已完成&已收单，可操作；
     * 1.1 不可操作提示语：工单已算账，不可改价格
     * 2 为：保内订单，可操作
     * 2.1 不可操作提示语：保外订单，完成后不允许改价格
     * 3 工单为：新单，可操作；
     * 3.1 不可操作提示语：退款单和返修单，不可改价格
     */
    private OperatePermissionVO serviceitemPermission(OrderWork orderWork, Integer operatorType) {

        // 判断是否为墙面订单
        WallTypeEnum wallTypeEnum = wallQuotationBService.isWallOrder(PilotCheckQuery.builder()
                .categId(orderWork.getShowCategId())
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .servCategId(orderWork.getServCategId())
                .build(), orderWork.getServProductGroupId(), orderWork.getServItemType());

        // 墙面订单不能修改价格
        if (Objects.nonNull(wallTypeEnum) && (!Objects.equals(operatorType,GlobalConsts.OPERATE_USER_TYPE_USER))) {
            return OperatePermissionVO.fail("只允许工程师在APP上进行报价或修改价格！");
        }

        // 如果是null 默认是员工操作
        operatorType = Optional.ofNullable(operatorType).orElse(GlobalConsts.OPERATE_USER_TYPE_STAFF);

        // 判断工单是否有后台产品
        Integer productId = orderWork.getProductId();
        if (NumberUtil.isNullOrZero(productId)) {
            return OperatePermissionVO.fail("工单还未确定具体产品 不可以操作");
        }

        // 工单未完成的失败情况下不可以操作
        Integer resultStatus = orderWork.getResultStatus();
        if (Objects.equals(resultStatus, OrderStatusConsts.WORK_RESULT_FAIL) && orderWork.getCompleteTime() == null) {
            return OperatePermissionVO.fail("工单未完成-失败 不可以操作");
        }

        // 返修单和退款单不可更改价格
        if (orderWork.getType() != OrderConsts.ORDER_TYPE_NEW) {
            return OperatePermissionVO.fail("退款单和返修单，不可改价格");
        }

        // 计价器3.0订单 && 修改人是员工 检测报告提交之后不允许修改
        if (Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE) && Objects.equals(GlobalConsts.OPERATE_USER_TYPE_STAFF, operatorType)) {
            OrderQuotationProcess orderQuotationProcess = orderQuotationProcessService.findByOrderId(orderWork.getOrderId());
            if (Objects.nonNull(orderQuotationProcess) && Objects.equals(orderQuotationProcess.getReportConfirmStatus(), GlobalConsts.YES)) {
                return OperatePermissionVO.fail("检测报告已提交，不可改价格");
            }
        }

        Integer orderStatus = orderWork.getStatus();
        if (orderStatus < OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE) {

            // 完成前
            List<Integer> supportStatusList = Lists
                    .newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE,
                            OrderStatusConsts.WORK_STATUS_VISIT);
            if (!supportStatusList.contains(orderWork.getStatus())) {
                return OperatePermissionVO.fail("工单未派单或已取消，不可改价格");
            }
        } else {

            //服务完成不能改价格
            return OperatePermissionVO.fail("工单已服务完成，不可改价格");

            // 完成后
            /*List<Integer> supportStatusList = Lists
                    .newArrayList(OrderStatusConsts.WORK_STATUS_COMPLETE, OrderStatusConsts.WORK_STATUS_CHECKOUT);
            if (!supportStatusList.contains(orderWork.getStatus())) {
                return OperatePermissionVO.fail("工单已算账，不可改价格");
            }

            if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
                return OperatePermissionVO.fail("保外订单，完成后不允许改价格");
            }*/
        }

        // 特权工单-延保订单，审核中或者审核通过不能改价格
        if (Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER) && NumberUtil.isNotNullOrZero(orderWork.getOriginalAmount())) {
            OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
            if (!Objects.isNull(orderMember)) {
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS
                        || orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单需延保复审或审核通过，不可改价格");
                }
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 核配件操作权限
     */
    private OperatePermissionVO partPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        Integer platWork = orderWork.getPlatWork();
        if (Objects.equals(GlobalConsts.PLAT_MARK_SAAS, platWork) || Objects.equals(GlobalConsts.PLAT_MARK_YEYX, platWork)) {
            return OperatePermissionVO.fail("言而有信和一步维修，不可核配件");
        }
        Integer resultStatus = orderWork.getResultStatus();

        // 已派单&已领单&已上门&已服务完成&已完成-进行中
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT,
                OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE, OrderStatusConsts.WORK_STATUS_COMPLETE);
        boolean statusSupport = supportStatusList.contains(orderWork.getStatus());
        if (!(statusSupport && Objects.equals(OrderStatusConsts.WORK_RESULT_DOING, resultStatus))) {
            return OperatePermissionVO.fail("工单未派单或已取消或已收单，不可核配件");
        }

        // 结果进行中、成功 或者 有完成时间的失败 可操作
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING, OrderStatusConsts.WORK_RESULT_SUCCESS);
        Date completeTime = orderWork.getCompleteTime();

        boolean resultStatusSupportA = supportResultStatusList.contains(orderWork.getResultStatus());
        boolean resultStatusSupportB = !Objects.isNull(completeTime) && Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL);

        if (!resultStatusSupportA && !resultStatusSupportB) {
            return OperatePermissionVO.fail("工单已取消或已算账，不可核配件");
        }

        // 退款单无需核配件
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return OperatePermissionVO.fail("退款单无需核配件！");
        }

        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("赔偿单无需核配件！");
        }

        /**
         * 计价器3.0订单 没有服务项不允许核配件
         */
        if (Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
            List<OrderServiceItem> orderServiceItems = orderServiceItemService.listByOrderId(orderWork.getOrderId());
            if (CollectionUtil.isNullOrEmpty(orderServiceItems)) {
                return OperatePermissionVO.fail("确定服务项目后才能操作");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 保修操作权限
     * 1、工单有后台产品，可操作；
     * 1.1、不可操作提示语：工单还未确定具体型号/属性，不可操作
     * 2、工单有：领单时间&未取消，可操作；
     * 1.1、不可操作提示语：工单还未派单或已取消，不可操作
     * 3、服务分类为：家电安装、家电维修，可操作；
     * 1.1、不可操作提示语：目前仅家电安装和维修，有保修卡
     */
    private OperatePermissionVO warrantyPermission(OrderWork orderWork) {

        /*if (orderWork.getServCategId() != GlobalConsts.SERV_CATEG_REPAIR && orderWork.getServCategId() != GlobalConsts.SERV_CATEG_INSTALL) {
            return OperatePermissionVO.fail("目前仅家电安装和维修，有保修卡");
        }*/

        if (Objects.equals(OrderConsts.ORDER_TYPE_REFUND,orderWork.getType())) {
            return OperatePermissionVO.fail("退款订单不可操作保修");
        }

        if (Objects.equals(OrderConsts.ORDER_TYPE_REWORK,orderWork.getType())) {
            return OperatePermissionVO.fail("返修订单不可操作保修");
        }

        if (Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE,orderWork.getType())) {
            return OperatePermissionVO.fail("返修订单不可操作保修");
        }

        // 产品id不能为空
        if (NumberUtil.isNullOrZero(orderWork.getProductId())) {
            return OperatePermissionVO.fail("工单还未确定具体型号/属性，不可操作");
        }

        if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {
            return OperatePermissionVO.fail("保内订单不可操作保修");
        }

        Date takeTime = orderWork.getTakeTime();
        Date resultTime = orderWork.getResultTime();

        List<Integer> supportResultStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_RESULT_DOING, OrderStatusConsts.WORK_RESULT_SUCCESS);

        boolean takeSupport = takeTime != null;
        boolean resultStatusSupport = supportResultStatusList.contains(orderWork.getResultStatus());

        if (!takeSupport) {
            return OperatePermissionVO.fail("工程师未领单不可操作");
        }

        // 已领单 已上门
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT);
        boolean supportStatus = supportStatusList.contains(orderWork.getStatus());

        List<Integer> resultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean supportResultStatus = resultStatusList.contains(orderWork.getResultStatus());

        // C：有：订单金额&应收
        Integer originalAmount = orderWork.getOriginalAmount();
        Integer totalAmount = orderWork.getTotalAmount();
        boolean supportB = originalAmount != null && totalAmount != null;
        if (!supportB) {
            return OperatePermissionVO.fail("请勾选服务项目，才可操作");
        }

        // 服务项必填
        List<OrderProductExtend> orderProductExtendList = orderProductExtendService.listByOrderId(orderWork.getOrderId());
        List<OrderServiceItem> orderServiceItemList = orderServiceItemService.listByOrderId(orderWork.getOrderId());
        Set<Long> collect = orderServiceItemList.stream().map(e -> e.getProExtId()).collect(Collectors.toSet());
        if (!Objects.equals(orderProductExtendList.size(), collect.size())) {
            return OperatePermissionVO.fail("服务项未填写完整，不可操作");
        }

        OrderWarranty orderWarranty = orderWarrantyService.findByOrderId(orderWork.getOrderId());

        // 新保修卡
        boolean isNewWarranty = Objects.nonNull(orderWarranty) && StringUtil.isBlank(orderWarranty.getCode());

        // 兼容权限校验
        if (resultStatusSupport && Objects.nonNull(orderWarranty)) {
            if (supportStatus && supportResultStatus && !isNewWarranty) {
                return OperatePermissionVO.fail("版本升级，暂时不支持后台操作，请到师傅端操作");
            }
        }

        Map<Long, Integer> warrantyMap = zsOrderWarrantyBService.isExistWarrantyInfoMap(orderWork.getOrderId(), orderWork.getWorkId());
        boolean notExistWarranty = !warrantyMap.containsValue(GlobalConsts.YES);


        if (notExistWarranty && Objects.isNull(orderWarranty) ) {
            return OperatePermissionVO.fail("当前产品的服务项目无保修卡");
        }

        if (resultTime != null && !resultStatusSupport) {
            return OperatePermissionVO.fail("订单已取消不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 配件报销操作权限
     */
    private OperatePermissionVO partReimbursePermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        Integer platWork = orderWork.getPlatWork();
        List<Integer> supportPlat = Lists.newArrayList(GlobalConsts.PLAT_MARK_ZMN, GlobalConsts.PLAT_MARK_CNHB);
        if (!supportPlat.contains(platWork)) {
            return OperatePermissionVO.fail("非啄木鸟/川南环保平台服务订单，不可操作");
        }

        // 订单中有待报销的外报单或订单杂项费用
        // 订单中存在待审核的外报单或订单杂项费用时不允许报销
        // 收单后才可配件审核
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_CHECKOUT) {
            return OperatePermissionVO.fail("收单后才可操作配件审核");
        }

        List<OrderPart> orderParts = orderPartService.listByOrderId(orderWork.getOrderId());
        boolean isReimburseDoing = orderParts.stream().anyMatch(orderPart ->
                !Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_SOURCING_IN)
                && Objects.equals(orderPart.getReimburseStatus(), OrderConsts.PART_REIMBURSE_STATUS_DOING));
        if (!isReimburseDoing) {
            return OperatePermissionVO.fail("只有订单包含待报销的外报单/订单杂项费用才可报销");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 开发票操作权限
     */
    private OperatePermissionVO invoicePermission(OrderWork orderWork) {
        try {
            ResponseDTO responseDTO = invoiceInfoModifyRemoteService.verifyOrderInvoice(orderWork.getOrderId(), orderWork.getWorkId());
            if (!responseDTO.isSuccess()) {
                return OperatePermissionVO.fail(responseDTO.getMessage());
            }
        } catch (ErpBaseException e) {
            return OperatePermissionVO.fail(e.getMessage());
        } catch (Exception e) {
            logger.error(String.format("校验是否可以操作开发票失败: %s", e.getMessage()));
            return OperatePermissionVO.fail(e.getMessage());
        }

        return OperatePermissionVO.success();
    }

    /**
     * 开票提醒操作权限
     */
    private OperatePermissionVO invoiceRemindPermission(OrderWork orderWork) {
        try {
            ResponseDTO responseDTO = invoiceInfoModifyRemoteService.verifyOrderInvoice(orderWork.getOrderId(), orderWork.getWorkId());
            if (!responseDTO.isSuccess()) {
                return OperatePermissionVO.fail(responseDTO.getMessage());
            }
        } catch (ErpBaseException e) {
            return OperatePermissionVO.fail(e.getMessage());
        } catch (Exception e) {
            logger.error(String.format("获取推送开票信息失败: %s", e.getMessage()));
            return OperatePermissionVO.fail(e.getMessage());
        }

        return OperatePermissionVO.success();
    }

    /**
     *  发票反馈操作权限
     * @param orderWork
     * @return
     */
    public OperatePermissionVO invoiceFeedBackPermission(OrderWork orderWork) {
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            return OperatePermissionVO.fail("派单后才可操作发票反馈");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 退款操作权限
     */
    private OperatePermissionVO refundPermission(OrderWork orderWork) {

        /*  1、工单状态：有完成时间，可操作
                - 不可操作提示语：工单未完成，不可建：退款单
            2、工单无：退款单，即当前工单未对应到退款工单，不可操作
                - 不可操作提示语：当前工单已建：退款单，不可重复退款*/

        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return OperatePermissionVO.fail("当前工单是退款单，不可建：退款单");
        }

        if (Objects.isNull(orderWork.getCompleteTime())) {
            return OperatePermissionVO.fail("工单未完成，不可建：退款单");
        }

        String redisKey = String.format(RedisKeyConsts.ORDER_OPERATE_REFUND_KEY, String.valueOf(orderWork.getOrderId()));
        if (redisManager.exists(redisKey)) {
            return OperatePermissionVO.fail("当前时间24小时内，已建立一张退款单，不可重复退款");
        }

        // 要客不能创建赔偿单
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        if (Objects.equals(orderDetail.getVvip(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("要客订单不能创建退款单");
        }

        OrderWorkQuery esQuery = new OrderWorkQuery();
        esQuery.setOrderId(orderWork.getOrderId());
        esQuery.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REFUND));
        List<EsOrderWork> esOrderWorks = orderWorkListBService.listPageOrderWorkByQuery(esQuery);
        if (CollectionUtil.isNotNullOrEmpty(esOrderWorks)) {
            long count = esOrderWorks.stream()
                    .filter(e -> Objects.equals(e.getPayStatus(),PayConsts.REFUND_STATUS_ING) || Objects.equals(e.getPayStatus(),PayConsts.REFUND_STATUS_PART))
                    .count();
            if (count > 0) {
                return OperatePermissionVO.fail("有进行中退款单，不可新建退款单");
            }
        }

        // 重复支付审核中不可操作
        List<OmsOrderReview> reviewList = orderReviewService.getOmsOrderReviewByOrderIdsAndType(Lists.newArrayList(orderWork.getWorkId()), OrderConsts.OMS_ORDER_REVIEW_DUPLICATE_PAY_REFUND);
        if (CollectionUtil.isNotNullOrEmpty(reviewList)) {
            boolean waitReview = reviewList.stream().anyMatch(e -> Objects.equals(e.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK));
            if (waitReview) {
                return OperatePermissionVO.fail("重复支付退款审核中，不可操作");
            }
        }
        return OperatePermissionVO.success();
    }

    /**
     * 跟单操作权限
     */
    private OperatePermissionVO trackPermission(OrderWork order) {

        // 完成前的弃单或失败=取消
        if (order.getStatus() < OrderStatusConsts.ORDER_STATUS_COMPLETE
                && (Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)
                || Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL))) {
            return OperatePermissionVO.fail("工单已取消，不可跟单");
        }

        // 非言而有信平台，已完成不能跟单
        if (!Objects.equals(order.getPlatWork(), GlobalConsts.PLAT_MARK_YEYX)) {
            if (order.getStatus() >= OrderStatusConsts.ORDER_STATUS_COMPLETE) {
                return OperatePermissionVO.fail("工单已完成，不可跟单");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 投诉操作权限
     */
    private OperatePermissionVO complaintPermission(OrderWork orderWork) {

        return OperatePermissionVO.success();
    }

    /**
     * 算账操作权限 - 子公司角色（不包括：子公司老总）
     */
    private OperatePermissionVO accountPermission(OrderWork orderWork) {
        // 非啄木鸟平台服务 不可操作
        //Integer platWork = orderWork.getPlatWork();
       /* if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        }*/
        // if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) && Objects
        //         .equals(orderWork.getPlatWork(), GlobalConsts.PLAT_MARK_YEYX)) {
        //     return OperatePermissionVO.fail("言而有信退款单暂不支持算账");
        // }

        // 校验是否已进入自动算账流程
        String redisKey = String.format(RedisKeyConsts.AUTO_ACCOUNT_LOCK_KEY, orderWork.getWorkId());
        if (redisManager.exists(redisKey)) {
            return OperatePermissionVO.fail("订单已进入自动算账流程，请稍后重试");
        }

        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_CHECKOUT);
        boolean statusSupport = supportStatusList.contains(orderWork.getStatus());
        if (!statusSupport) {
            return OperatePermissionVO.fail("工单不是已收单状态，不可操作");
        }

        if (Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F) && !Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE) && Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            if (!ChannelConsts.CHANNEL_ID_NOSUPPORT_ACCOUNT_PAY.contains(orderWork.getChannelId())) {
                return OperatePermissionVO.fail("厂商余额不足，该订单未支付，请先充值");
            }
        }

        Integer platWork = orderWork.getPlatWork();
        if (Objects.equals(platWork, GlobalConsts.PLAT_MARK_CNHB)) {
            return OperatePermissionVO.success();
        }

        // 退款单收单，不需检验源单有无待审核外报、运杂申请
        if (Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())) {
            // 原单需要已算账状态
            OrderWork originalOrderWork = orderWorkService.findOrderWorkByKey(orderWork.getOrderId(), orderWork.getOriginalId());
            if (!Objects.equals(originalOrderWork.getStatus(), OrderStatusConsts.WORK_STATUS_ACCOUNT)) {
                return OperatePermissionVO.fail("原单未算账，退款单不可算账！");
            }
        }

        if (Objects.equals(platWork, GlobalConsts.PLAT_MARK_YEYX)) {
            if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)) {
                return OperatePermissionVO.fail("工单收单结果为：失败，不可算账");
            }
            return OperatePermissionVO.success();
        }

        // 承包加盟工程师 不需要核配件
        boolean isDirect = false;
        // todo fubiao
        logger.info("accountPermission#getEngineerDetailById 入参 [{}]",orderWork.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService
                .getEngineerDetailById(orderWork.getMasterId());
        logger.info("accountPermission#getEngineerDetailById 出参 [{}]",JSON.toJSONString(cacheEngineerByEngineerId));
        if (!cacheEngineerByEngineerId.isSuccess() || cacheEngineerByEngineerId.getData() == null) {
            isDirect = false;
        } else {
            Integer agent = cacheEngineerByEngineerId.getData().getCooperationType();
            isDirect = Objects.equals(agent, GlobalConsts.NO);
        }

        // 维修安装
        List<Integer> supportServCategList = Lists
                .newArrayList(GlobalConsts.SERV_CATEG_REPAIR, GlobalConsts.SERV_CATEG_INSTALL);

        // 必须操作过配件 （工程师app 或者后台核配件），不包括退款单， 不包括承包加盟工程师
        Integer partUse = orderWork.getPartUse();
        if (supportServCategList.contains(orderWork.getServCategId())
                && isDirect
                && !Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())
                && !Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, orderWork.getType())
                && Objects.equals(GlobalConsts.NONE, partUse)) {
            return OperatePermissionVO.fail("工单未完成，或已收单，不可操作");
        }

        // 开发票公司判断
        OrderInvoice orderInvoice = orderInvoiceService.findOrderInvoiceByKey(orderWork.getOrderId());
        if (orderInvoice != null && NumberUtil.isNullOrZero(orderInvoice.getCompanyId())) {
            return OperatePermissionVO.fail("未填写开发票的公司，不可操作");
        }

        // 多工程师有分润值
        if ((Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK))) {


            // TODO 数据修正 liuying 多师傅状态数据修复
            List<OrderMaster> orderMasterList = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
            try {
                if (CollectionUtils.isNotEmpty(orderMasterList)) {
                    if (orderMasterList.size() > 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.YES)) {
                        OrderWork updateOrderWork = new OrderWork();
                        updateOrderWork.setOrderId(orderWork.getOrderId());
                        updateOrderWork.setWorkId(orderWork.getWorkId());
                        updateOrderWork.setMultiMaster(GlobalConsts.YES);
                        updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                        updateOrderWork.setUpdateTime(DateUtil.getNow());
                        orderWorkService.saveMultiMaster(updateOrderWork);

                        orderWork.setMultiMaster(GlobalConsts.YES);
                    } else if (orderMasterList.size() == 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.NO)) {
                        OrderWork updateOrderWork = new OrderWork();
                        updateOrderWork.setOrderId(orderWork.getOrderId());
                        updateOrderWork.setWorkId(orderWork.getWorkId());
                        updateOrderWork.setMultiMaster(GlobalConsts.NO);
                        updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                        updateOrderWork.setUpdateTime(DateUtil.getNow());
                        orderWorkService.saveMultiMaster(updateOrderWork);

                        orderWork.setMultiMaster(GlobalConsts.NO);
                    }
                }
            } catch (Exception ex){}

            if (Objects.equals(orderWork.getMultiMaster(), GlobalConsts.YES)) {
                // List<OrderMaster> orderMasters = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
                boolean opMasterSharing = orderMasterBService.checkMasterSharing(orderWork);
                if (!opMasterSharing) {
                    return OperatePermissionVO.fail("工程师分润未设置，不可操作！");
                }
            }

        }

        return OperatePermissionVO.success();
    }

    /**
     * 异常操作权限
     */
    private OperatePermissionVO abnormalPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        Integer platWork = orderWork.getPlatWork();
        if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 会员单平台审核操作权限
     */
    private OperatePermissionVO memPlatReviewPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        Integer platWork = orderWork.getPlatWork();
        if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        }

        if (!Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            return OperatePermissionVO.fail("非会员单");
        }

        OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
        if (Objects.isNull(orderMember)) {
            return OperatePermissionVO.fail("非会员单");
        }

        Integer verify = orderMember.getVerify();
        if (!Objects.equals(verify, GlobalConsts.YES)) {
            return OperatePermissionVO.fail("该会员单无需审核");
        }

        if (orderMember.getReviewStatus() < OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) {
            return OperatePermissionVO.fail("请等待工程师审核通过");
        }

        if (null == orderWork.getOriginalAmount()) {
            return OperatePermissionVO.fail("工程师还未确定订单价格");
        }

        boolean failedBeforeComplete = orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_COMPLETE
                && orderWork.getResultStatus() == OrderStatusConsts.WORK_RESULT_FAIL;
        boolean discard = Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD);
        if (failedBeforeComplete || discard) {
            return OperatePermissionVO.fail("工单已取消，无需审核");
        }

        // 已完成 - 进行中 才可以操作
        /*Date completeTime = orderWork.getCompleteTime();
        if (completeTime == null) {
            return OperatePermissionVO.fail("订单不是已完成状态，不可审核");
        }*/
        /*Integer resultStatus = orderWork.getResultStatus();
        if (!Objects.equals(resultStatus, OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("订单不是已完成状态，不可审核");
        }*/

        // 待平台审核
        Integer reviewStatus = orderMember.getReviewStatus();
        Integer reviewResult = orderMember.getReviewResult();
        if (!Objects.equals(reviewResult, OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
            return OperatePermissionVO.fail("订单已经审核成功/失败，不可在审核");
        }
        if (!Objects.equals(reviewStatus, OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT)) {
            return OperatePermissionVO.fail("订单暂时无需后台审核");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 子公司角色（不含：子公司老总）
     * 收单操作权限
     */
    private OperatePermissionVO checkoutPermission(OrderWork orderWork) {

        // 已完成，并且：已核配件，可操作
        List<Integer> supportStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_COMPLETE, OrderStatusConsts.WORK_STATUS_CHECKOUT);
        boolean statusSupport = supportStatusList.contains(orderWork.getStatus());
        if (!statusSupport) {
            return OperatePermissionVO.fail("工单未完成，或已算账，不可操作");
        }

        // 保留配件申请24小时
        if (Objects.equals(orderWork.getPartRetain(), com.zmn.consts.GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师保留配件申请24小时，暂不能收单");
        }

        // 若是需审核的会员单，还需后台审核后，才可收单
        Integer member = orderWork.getMember();
        if (Objects.equals(member, GlobalConsts.YES)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
            boolean verify = Objects.equals(orderMember.getVerify(), GlobalConsts.YES);
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (verify && !reviewSuccess) {
                return OperatePermissionVO.fail("会员工单还未审核，不可操作");
            }
        }

        Integer platWork = orderWork.getPlatWork();
        if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN) && !Objects
                .equals(platWork, GlobalConsts.PLAT_MARK_CNHB)) {
            return OperatePermissionVO.success();
        }

        // 多工程师有分润值
        if ((Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK))) {


            // TODO liuying 多师傅状态数据修复
            List<OrderMaster> orderMasterList = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
            try {
                if (CollectionUtils.isNotEmpty(orderMasterList)) {
                    if (orderMasterList.size() > 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.YES)) {
                        OrderWork updateOrderWork = new OrderWork();
                        updateOrderWork.setOrderId(orderWork.getOrderId());
                        updateOrderWork.setWorkId(orderWork.getWorkId());
                        updateOrderWork.setMultiMaster(GlobalConsts.YES);
                        updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                        updateOrderWork.setUpdateTime(DateUtil.getNow());
                        orderWorkService.saveMultiMaster(updateOrderWork);

                        orderWork.setMultiMaster(GlobalConsts.YES);
                    } else if (orderMasterList.size() == 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.NO)) {
                        OrderWork updateOrderWork = new OrderWork();
                        updateOrderWork.setOrderId(orderWork.getOrderId());
                        updateOrderWork.setWorkId(orderWork.getWorkId());
                        updateOrderWork.setMultiMaster(GlobalConsts.NO);
                        updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                        updateOrderWork.setUpdateTime(DateUtil.getNow());
                        orderWorkService.saveMultiMaster(updateOrderWork);

                        orderWork.setMultiMaster(GlobalConsts.NO);
                    }
                }
            } catch (Exception ex){}

            if (Objects.equals(orderWork.getMultiMaster(), GlobalConsts.YES)) {
                // List<OrderMaster> orderMasters = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());

                boolean opMasterSharing = orderMasterBService.checkMasterSharing(orderWork);
                if (!opMasterSharing) {
                    return OperatePermissionVO.fail("工程师分润未设置，不可操作！");
                }
            }

        }

        // 承包加盟工程师 不需要核配件
        boolean isDirect = false;
        // todo fubiao
        logger.info("checkoutPermission#getEngineerDetailById 入参 [{}]",orderWork.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService
                .getEngineerDetailById(orderWork.getMasterId());
        logger.info("checkoutPermission#getEngineerDetailById 出参 [{}]",JSON.toJSONString(cacheEngineerByEngineerId));
        if (!cacheEngineerByEngineerId.isSuccess() || cacheEngineerByEngineerId.getData() == null) {
            isDirect = false;
        } else {
            Integer agent = cacheEngineerByEngineerId.getData().getCooperationType();
            isDirect = Objects.equals(agent, GlobalConsts.NO);
        }

        // 维修安装
        List<Integer> supportServCategList = Lists
                .newArrayList(GlobalConsts.SERV_CATEG_REPAIR, GlobalConsts.SERV_CATEG_INSTALL);

        // 必须操作过配件 （工程师app 或者后台核配件），不包括退款单， 不包括承包加盟工程师
        Integer partUse = orderWork.getPartUse();
        if (supportServCategList.contains(orderWork.getServCategId()) && isDirect
                && !Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())
                && !Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, orderWork.getType())
                && Objects.equals(GlobalConsts.NONE, partUse)) {
            return OperatePermissionVO.fail("工单未核配件，不可收单");
        }

        // 工单服务平台是“啄木鸟和川南环保”，不是退款单，则必须要先：核配件，才可操作
        if (Objects.equals(partUse, GlobalConsts.NONE)
                && (Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN) || Objects.equals(platWork, GlobalConsts.PLAT_MARK_CNHB))
                && !Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())
                && !Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, orderWork.getType())
        ) {
            return OperatePermissionVO.fail("工单未核配件，不可收单");
        }

        // 如果订单存在老仓储配件则不能收单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            List<OrderPart> partList = orderPartService.listOrderPartByOrderId(orderWork.getOrderId());
            for (OrderPart orderPart : partList){
                // 内采配件，支付方式为0，则是老仓储数据，返回空List
                if (Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_SOURCING_IN)
                        && Objects.equals(orderPart.getPayType(), GlobalConsts.NONE)){
                    return OperatePermissionVO.fail("该订单存在老仓储内采配件不能收单，请重新选择内采配件");
                }
                // 外报和运杂配件，报销单号为null，则是老仓储数据，返回空List
                if ((Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_SOURCING_OUT)
                        || Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_DELIVER))
                        && Objects.isNull(orderPart.getReimburseId())){
                    return OperatePermissionVO.fail("该订单存在老仓储外报配件或运杂费不能收单，请重新选择外报配件或运杂费");
                }
            }
        }

        // 要客不做金额限制 modify by liuying 2021-10-11
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        // 新单，配件金额之和不得大于订单收入
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                && !Objects.equals(orderDetail.getVvip(), GlobalConsts.YES)) {
            List<OrderPart> parts = orderPartService.listByOrderId(orderWork.getOrderId());
            if (CollectionUtil.isNotNullOrEmpty(parts)) {
                Integer partTotalAmount = parts.stream().mapToInt(item -> {
                    return MathUtil.amountMultiplyNumber(item.getPrice(), item.getNumber());
                }).sum();
                if (partTotalAmount > orderWork.getTotalAmount()) {
                    return OperatePermissionVO.fail("配件金额大于订单收入，不可完成");
                }
            }
        }

        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)
                && !Objects.equals(orderWork.getPayStatus(), PayConsts.REFUND_STATUS_DONE)) {
            return OperatePermissionVO.fail("未退款成功，不可操作");
        }

        // 仓储检查权限
        OperatePermissionVO existsSCMToAuditPartsOPV = this.existsSCMToAuditParts(orderWork.getOrderId(), orderWork.getType());
        if (!existsSCMToAuditPartsOPV.getCanOperate()) {
            return OperatePermissionVO.fail(existsSCMToAuditPartsOPV.getMsg());
        }

        return OperatePermissionVO.success();
    }

    /**
     * 收单 - 子公司老总&总部角色
     *
     * @param orderWork
     * @return
     */
    private OperatePermissionVO adminCheckoutPermission(OrderWork orderWork) {

        // 非啄木鸟平台服务 不可操作
        // Integer platWork = orderWork.getPlatWork();
       /* if (!Objects.equals(platWork, GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("非啄木鸟平台服务订单，不可操作");
        }*/

        // 已完成&已收单状态，并且：已核配件，可操作
        List<Integer> supportStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_COMPLETE, OrderStatusConsts.WORK_STATUS_CHECKOUT);
        boolean statusSupport = supportStatusList.contains(orderWork.getStatus());
        if (!statusSupport) {
            return OperatePermissionVO.fail("工单未完成，或已算账，不可操作");
        }

        Integer platWork = orderWork.getPlatWork();
        if (Objects.equals(platWork, GlobalConsts.PLAT_MARK_YEYX)) {
            return OperatePermissionVO.success();
        }

        // 承包加盟工程师 不需要核配件
        boolean isDirect = false;
        // todo fubiao
        logger.info("adminCheckoutPermission#getEngineerDetailById 入参 [{}]",orderWork.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService
                .getEngineerDetailById(orderWork.getMasterId());
        logger.info("adminCheckoutPermission#getEngineerDetailById 出参 [{}]",JSON.toJSONString(cacheEngineerByEngineerId));
        if (!cacheEngineerByEngineerId.isSuccess() || cacheEngineerByEngineerId.getData() == null) {
            isDirect = false;
        } else {
            Integer agent = cacheEngineerByEngineerId.getData().getCooperationType();
            isDirect = Objects.equals(agent, GlobalConsts.NO);
        }

        // 维修安装
        List<Integer> supportServCategList = Lists
                .newArrayList(GlobalConsts.SERV_CATEG_REPAIR, GlobalConsts.SERV_CATEG_INSTALL);

        // 必须操作过配件 （工程师app 或者后台核配件），不包括退款单， 不包括承包加盟工程师
        Integer partUse = orderWork.getPartUse();
        if (supportServCategList.contains(orderWork.getServCategId())
                && isDirect
                && !Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())
                && !Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, orderWork.getType())
                && Objects.equals(GlobalConsts.NONE, partUse)) {
            return OperatePermissionVO.fail("工单未完成，或已收单，不可操作");
        }

        // 若是需审核的会员单，还需后台审核后，才可收单
        Integer member = orderWork.getMember();
        if (Objects.equals(member, GlobalConsts.YES)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(orderWork.getOrderId());
            boolean verify = Objects.equals(orderMember.getVerify(), GlobalConsts.YES);
            boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
            if (verify && !reviewSuccess) {
                return OperatePermissionVO.fail("会员工单还未审核，不可操作");
            }
        }

        // 如果订单存在老仓储配件则不能收单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            List<OrderPart> partList = orderPartService.listOrderPartByOrderId(orderWork.getOrderId());
            for (OrderPart orderPart : partList){
                // 内采配件，支付方式为0，则是老仓储数据，返回空List
                if (Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_SOURCING_IN)
                        && Objects.equals(orderPart.getPayType(), GlobalConsts.NONE)){
                    return OperatePermissionVO.fail("该订单存在老仓储内采配件不能收单，请重新选择内采配件");
                }
                // 外报和运杂配件，报销单号为null，则是老仓储数据，返回空List
                if ((Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_SOURCING_OUT)
                        || Objects.equals(orderPart.getPartType(), OrderConsts.PART_TYPE_DELIVER))
                        && Objects.isNull(orderPart.getReimburseId())){
                    return OperatePermissionVO.fail("该订单存在老仓储外报配件或运杂费不能收单，请重新选择外报配件或运杂费");
                }
            }
        }

        // 仓储检查权限
        OperatePermissionVO existsSCMToAuditPartsOPV = this.existsSCMToAuditParts(orderWork.getOrderId(), orderWork.getType());
        if (!existsSCMToAuditPartsOPV.getCanOperate()) {
            return OperatePermissionVO.fail(existsSCMToAuditPartsOPV.getMsg());
        }

        return OperatePermissionVO.success();
    }

    /**
     *是否存在SCM 待审核配件
     * @return
     */
    @Override
    public OperatePermissionVO existsSCMToAuditParts(Long orderId, Integer type) {
        // 退款单收单，不需检验源单有无待审核外报、运杂申请
        if (!(Objects.equals(OrderConsts.ORDER_TYPE_REFUND, type) || Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, type))) {
            List<OrderPart> partList = orderPartService.listByOrderId(orderId);
            List<String> list = partList.stream()
                    .filter(part -> Objects.equals(part.getPartType(), OrderConsts.PART_TYPE_SOURCING_OUT)
                            || Objects.equals(part.getPartType(), OrderConsts.PART_TYPE_DELIVER))
                    .map(OrderPart::getReimburseId).distinct()
                    .collect(Collectors.toList());

            try {
                // 存在待审核的外报和运杂不可报销
                ResponseDTO<Boolean> responseDTO = engineerPurchaseModifyRemoteService.checkExistUnaudited(
                        orderId, list);
                if (!responseDTO.isSuccess()) {
                    logger.error("dubbo interface fail!");
                    return OperatePermissionVO.fail("检查待审核的外报运杂失败");
                }

                Boolean exist = responseDTO.getData();
                if (exist != null && exist) {
                    return OperatePermissionVO.fail("供应链存在外报或运杂未审核，不可操作");
                }
            } catch (Exception ex) {
                return OperatePermissionVO.fail("检查待审核的外报运杂失败");
            }
        }
        return OperatePermissionVO.success();
    }

    /**
     * 挂起操作权限
     */
    private OperatePermissionVO suspendPermission(OrderWork order) {
        //判断是否有预约时间(需求变更不需要判断)
        // if (Objects.isNull(order.getDutyTime())) {
        //     return OperatePermissionVO.fail("工单暂无预约时间，无法挂起");
        // }
        // A：已派单或已领单或已上门-进行中
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        List<Integer> supportStatus = Lists.newArrayList(
                OrderStatusConsts.WORK_STATUS_INPUT,
                OrderStatusConsts.WORK_STATUS_CONFIRM,
                OrderStatusConsts.WORK_STATUS_ASSIGN,
                OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE,
                OrderStatusConsts.WORK_STATUS_VISIT);
        boolean resultstatus = supportStatus.contains(order.getStatus());
        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean support = resultstatus && resultStatusSupport;
        if (!support) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可挂起");
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作挂起");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 服务完成操作权限
     */
    private OperatePermissionVO serviceCompletePermission(OrderWork order, Integer operatorType) {
        if (!Objects.equals(GlobalConsts.OPERATE_USER_TYPE_MASTER, operatorType)) {
            if (ChannelConsts.CHANNEL_ID_DISABLED_SERVCOMPLETE.contains(order.getChannelId())) {
                return OperatePermissionVO.fail("该渠道不允许在后台操作服务完成");
            }
        }

        //1、已派单/已领单/已上门-进行中
        if (!((Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE)
                || Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE)
                || Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_VISIT)) && Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING))) {
            return OperatePermissionVO.fail("工单未派单或已完成或已取消，不可操作");
        }
        //2、订单业务类型：F端订单
        if (!Objects.equals(order.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {
            return OperatePermissionVO.fail("仅F端订单可操作服务完成");
        }
        //3、有：订单金额&订单收入
        if (Objects.isNull(order.getOriginalAmount()) && Objects.isNull(order.getTotalAmount())) {
            return OperatePermissionVO.fail("请先填写价格或勾选服务项目，才可操作");
        }

        // 4,天猫订单，不能存在工程师收款
        if (ChannelConsts.CHANNEL_ID_NOSUPPORT_ACCOUNT_PAY.contains(order.getChannelId())
                && NumberUtil.isNotNullOrZero(order.getMasterAmount())) {
            return OperatePermissionVO.fail("天猫订单，不能存在工程师收款");
        }
        // 存在保修卡
        Map<Long, Integer> warrantyMap = zsOrderWarrantyBService.isExistWarrantyInfoMap(order.getOrderId(), order.getWorkId());
        boolean existWarranty = warrantyMap.containsValue(GlobalConsts.YES);

        // E: 若家电维修&安装，需有：保修内容（啄木鸟平台）
        if (Objects.equals(order.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN)) {
            OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
            Integer servCategId = orderDetail.getServCategId();
            List<Integer> supportServCategList = Lists.newArrayList(GlobalConsts.SERV_CATEG_REPAIR, GlobalConsts.SERV_CATEG_INSTALL);
            if (supportServCategList.contains(servCategId)) {
                List<OrderWarrantyProduct> orderWarrantyProducts = orderWarrantyProductService.listByOrderId(order.getOrderId());
                if (orderWarrantyProducts.isEmpty() && existWarranty) {
                    return OperatePermissionVO.fail("工单无保修内容，请先勾选或后台操作：保修信息");
                }
            }
        }

        //1.5、渠道相关限制：
        if (Objects.equals(order.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_WYG)) {
            // 天猫订单扩展数据
            OrderTmallExtend orderTmallExtend = orderTmallExtendBService.findOrderTmallExtendByOrderId(order.getOrderId());
            if (!Objects.equals(orderTmallExtend.getVerification(), GlobalConsts.YES)) {
                return OperatePermissionVO.fail("核销未完成，不可操作");
            }
        }

        // 工程师收款金额 > 0 时，不可服务完成，仅针对渠道ID：10133、31055；
        if (Objects.equals(order.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_WYG)
                || Objects.equals(order.getChannelId(), OrderConsts.CHANNEL_ID_TMALL_BUSINESS)) {
            if (NumberUtil.isNotNullOrZero(order.getMasterAmount()) && order.getMasterAmount() > 0) {
                return OperatePermissionVO.fail("天猫渠道，工程师收款金额必须为：0");
            }
        }

        if (Objects.isNull(order.getDutyTime())) {
            return OperatePermissionVO.fail("工单无预约时间，不可服务完成");
        }

        // 渠道附件检查
        OrderAttachmentQuery orderAttachmentQuery = new OrderAttachmentQuery();
        orderAttachmentQuery.setOrderId(order.getOrderId());
        orderAttachmentQuery.setWorkId(order.getWorkId());
        orderAttachmentQuery.setBizType(order.getBizType());
        orderAttachmentQuery.setChannelId(order.getChannelId());
        orderAttachmentQuery.setServCategId(order.getServCategId());
        OperatePermissionVO requireAttachment = this.requireOrderChannelAttachment(orderAttachmentQuery);
        if (!requireAttachment.getCanOperate()) {
            return requireAttachment;
        }

        // 校验多次收款
        List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterIdSrcMaster(order.getOrderId(), order.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            boolean noVisit = orderVisitList.stream()
                    .anyMatch(e -> Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY)
                            || Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT));
            if (noVisit) {
                return OperatePermissionVO.fail("工单需再次上门，不可操作");
            }

            boolean noPay = orderVisitList.stream()
                    .filter(e -> NumberUtil.isNotNullOrZero(e.getAcceptanceId())
                            || NumberUtil.isNotNullOrZero(e.getOrderPayId()))
                    .filter(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL))
                    .anyMatch(e -> Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE));
            if (noPay) {
                return OperatePermissionVO.fail("工单未支付，不可操作");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 完成操作权限
     */
    private OperatePermissionVO completePermission(OrderWork order, Long operatorId, Integer operatorType) {
        // 禁止后台完成的渠道
        if (ChannelConsts.DISABLE_COMPLETE_CHANNEL_IDS.contains(order.getChannelId())) {
            return OperatePermissionVO.fail("该渠道不可后台完成，不可操作");
        }
        // 子公司员工操作限制
        boolean isSubCompanyStaff = isSubCompanyStaff(operatorType, operatorId);
        OperatePermissionVO operatePermissionVO = this.collectionNotPayCheck(order, OrderConsts.ORDER_OP_TYPE_COMPLETE, isSubCompanyStaff);
        if (!operatePermissionVO.getCanOperate()) {
            return operatePermissionVO;
        }

        /*
        A：已领单，已上门-进行中
        B：服务项必填
        C：有：订单金额&应收
        D：并且无：未支付定金
        E：若家电维修&安装，需有：保修内容
        F: 订单来源类型 会员单或厂商单不可操作完成+非：保内工单或会员工单
        G: 言而有信服务平台
        */

        // A：已派单或已领单或已上门-进行中
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        List<Integer> supportStatus = Lists
                .newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE,
                        OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE);
        boolean resultstatus = supportStatus.contains(order.getStatus());
        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean support = resultstatus && resultStatusSupport;

        // F端工单服务审核成功之后，才可以完成
        if (Objects.equals(order.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F)) {
            support = support && Objects.equals(order.getServiceCompleteReviewStatus(), OrderConsts.REVIEW_STATUS_SUCCESS);
        }

        if (!support) {
            return OperatePermissionVO.fail("工单未派单或未服务完成或已完成或已取消，不可操作");
        }

        // B: 服务项必填
        List<OrderProductExtend> orderProductExtendList = orderProductExtendService.listByOrderId(order.getOrderId());
        List<OrderServiceItem> orderServiceItemList = orderServiceItemService.listByOrderId(order.getOrderId());
        Set<Long> collect = orderServiceItemList.stream().map(e -> e.getProExtId()).collect(Collectors.toSet());
        if (!Objects.equals(orderProductExtendList.size(), collect.size())) {
            return OperatePermissionVO.fail("服务项未填写完整，不可操作");
        }

        // C：有：订单金额&应收
        Integer originalAmount = order.getOriginalAmount();
        Integer totalAmount = order.getTotalAmount();
        boolean supportB = originalAmount != null && totalAmount != null;
        if (!supportB) {
            return OperatePermissionVO.fail("请先填写价格or勾选服务项目，才可操作");
        }

        // D: 无：未支付定金
        Integer depositAmount = order.getDepositAmount();
        Integer depositStatus = order.getDepositStatus();

        boolean unSupportC = depositAmount != null && Objects.equals(PayConsts.PAY_STATUS_NONE, depositStatus);
        if (unSupportC) {
            return OperatePermissionVO.fail("有未支付定金，请先清空定金");
        }

        // 存在保修卡
        Map<Long, Integer> warrantyMap = zsOrderWarrantyBService.isExistWarrantyInfoMap(order.getOrderId(), order.getWorkId());
        boolean existWarranty = warrantyMap.containsValue(GlobalConsts.YES);

        // E: 需有：保修内容（啄木鸟/川南平台）
        if (Objects.equals(order.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN) || Objects.equals(order.getPlatWork(), GlobalConsts.PLAT_MARK_CNHB)) {
            List<OrderWarrantyProduct> orderWarrantyProducts = orderWarrantyProductService.listByOrderId(order.getOrderId());
            if (orderWarrantyProducts.isEmpty() && existWarranty) {
                return OperatePermissionVO.fail("无保修内容，请让工程师勾选保修内容");
            }
        }

        // 会员单,后台未审核不可完成
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember) && Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                    .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
            }
        }

        // F: 非：会员工单
        /*Integer sourceType = order.getSourceType();
        if (Objects.equals(sourceType, OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            return OperatePermissionVO.fail("延保工单，只可在工程师app，操作：完成");
        }*/
        Date dutyTime = order.getDutyTime();
        if (dutyTime == null) {
            return OperatePermissionVO.fail("工单还未确定预约时间，不可：完成");
        }

        // 检测完成
        try {
            CompleteDTO completeDTO = new CompleteDTO();
            completeDTO.setWorkId(order.getWorkId());
            completeDTO.setOrderId(order.getOrderId());
            completeDTO.setOperatorType(NumberUtil.isNullOrZero(operatorType) ? GlobalConsts.OPERATE_USER_TYPE_SYSTEM : operatorType);
            zsMasterWorkBService.checkWarrantyPay(completeDTO,order,Boolean.TRUE);
            zsNormalMasterWorkBService.checkComplete(completeDTO);
        } catch (Exception e) {
            if (e instanceof OmsBaseException) {
                return OperatePermissionVO.fail(e.getMessage());
            } else {
                logger.error(e.getMessage(), e);
                return OperatePermissionVO.fail("操作失败");
            }
        }

        if (isSubCompanyStaff) {
            TagsDRO oneBaseCodeMap = baseCodeService.getOneBaseCodeMap(order.getPlatWork(), OrderBaseCodeMapConsts.CODE_SUB_COMPANY_MAX_COMPLETED_COUNT, null);
            if (oneBaseCodeMap != null && oneBaseCodeMap.getTwoTypeId() != null) {
                Integer maxCompletedCount = oneBaseCodeMap.getTwoTypeId();
                Long count = statOrderBService.countCompletedOrderByCompleteId(operatorId, DateUtil.getMonthFirstDay(DateUtil.getNow()), null);
                logger.info("工单完成操作[{}]权限处理，子公司员工ID:{} 完成工单次数：{}，最多{}次", order.getWorkId(), operatorId, count, maxCompletedCount);
                if (count >= maxCompletedCount) {
                    return OperatePermissionVO.fail("超出本月‘完成’操作限制次数，不可操作");
                }
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 判断是否为子公司操作员
     *
     * @param operatorId
     * @return
     */
    private boolean isSubCompanyStaff(Integer operatorType, Long operatorId) {
        if (operatorId == null) {
            return false;
        }
        if (!Objects.equals(operatorType, GlobalConsts.OPERATE_USER_TYPE_STAFF)) {
            return false;
        }
        ResponseDTO<StaffDRO> staffDROResponseDTO = staffListRemoteService.getStaff(operatorId.intValue());
        StaffDRO staffDRO = staffDROResponseDTO.getData();
        // logger.info("staffDRO==={}", JSON.toJSONString(staffDRO));
        if (staffDRO == null) {
            return false;
        }

        Integer orgId = staffDRO.getOrgId();
        ResponseDTO<OrganizeDRO> organDROResponseDTO = organizeListRemoteService.getByKey(orgId);
        OrganizeDRO organDRO = organDROResponseDTO.getData();
        // logger.info("organDRO==={}", JSON.toJSONString(organDRO));
        if (organDRO == null) {
            return false;
        }
        return organDRO.getLevel() == null || organDRO.getLevel() > GlobalConsts.LEVEL_2;
    }


    /**
     * 派单操作权限
     */
    private OperatePermissionVO distributePermission(OrderWork order) {

        // 挂起状态，不可操作
        if (Objects.equals(order.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            return OperatePermissionVO.fail("挂起状态，不可操作");
        }

        // 退款单赔偿单，不可操作
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)
                || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("退款单/赔偿单，不可操作");
        }

        // C端订单，必须有预约时间，才可操作
        if (order.getDutyTime() == null && Objects.equals(order.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            return OperatePermissionVO.fail("请先确定预约时间，再派单");
        }

        if (this.isWaitPrePay(order)) {
            return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
        if (StringUtils.isBlank(orderDetail.getContactName())) {
            return OperatePermissionVO.fail("工单联系人姓名不规范，请调整后派单");
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作派单");
        }

        // 会员单，工程师审核后不能派单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        // 结果：已分单 - 进行中，可操作
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ASSIGN,OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT);

        // 是否网格化派单
        boolean isGrid = zsDistributeWorkBService.isGridDistribute(order);
        if (isGrid){
            supportStatusList.add(OrderStatusConsts.WORK_STATUS_CONFIRM);
        }

        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());

        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("工单未确认或未分单或已取消或已完成，不可操作");
        }

        // 取消跟单状态
        OperatePermissionVO operatePermissionVO = workTrackBService.getOperatePermissionByTrack(order.getOrderId(), order.getWorkId());
        if (Objects.equals(operatePermissionVO.getCanOperate(), false)) {
            return operatePermissionVO;
        }

        // 取消申请
        OperatePermissionVO operatePermission = cancelApplyBService.getOperatePermission(order.getOrderId(), order.getWorkId());
        if (Objects.equals(operatePermission.getCanOperate(), false)) {
            return operatePermission;
        }


        // 应用动态库存试点才判断
        if (orderStockBService.isWhiteWorkCity(order.getCityId())) {
            // 如果预约时间比当前时间小，提示不可操作
            if (Objects.nonNull(order.getDutyTime())) {
                if (order.getDutyTime().getTime() < DateUtil.getDateStart(DateUtil.getNow()).getTime()) {
                    return OperatePermissionVO.fail("预约时间为历史时间，请重新确认预约时间后派单");
                }
            }
        }

        // 返修单申请的退款单，如果退款单未完成，则该返修单不能改派
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            OrderWork original = orderWorkService.findOrderWorkByKey(order.getOriginalId(), order.getOriginalId());
            if (NumberUtil.isNotNullOrZero(original.getRefundTargetWorkId())) {
                OrderWork reworkRefund = orderWorkService.findOrderWorkByKey(original.getOrderId(), original.getRefundTargetWorkId());
                if (reworkRefund.getStatus() < OrderStatusConsts.ORDER_STATUS_COMPLETE
                        && Objects.equals(reworkRefund.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)
                        && Objects.equals(order.getOrderId(), reworkRefund.getRefundWorkId())) {
                    return OperatePermissionVO.fail("源单存在未完结的退款申请，不可操作");
                }
            }
        }

        // 存在已上门子流程，不允许改派
        /*List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterId(order.getOrderId(), order.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            boolean hasVisit = orderVisitList.stream().anyMatch(e -> Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_VISIT));
            if (hasVisit) {
                return OperatePermissionVO.fail("存在已上门子流程，不允许改派");
            }
            boolean hasPay = orderVisitList.stream()
                    .anyMatch(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)
                            && Objects.equals(e.getPayStatus(), PayConsts.PAY_STATUS_NONE)
                            && (NumberUtil.isNotNullOrZero(e.getOrderPayId())
                            || NumberUtil.isNotNullOrZero(e.getAcceptanceId())));
            if (hasPay) {
                return OperatePermissionVO.fail("存在待支付子流程，不允许改派");
            }
        }*/

        return OperatePermissionVO.success();
    }

    /**
     * 派单操作权限
     */
    private OperatePermissionVO distributeNewPermission(OrderWork order) {
        // 原有派单基础上添加前置条件
        try {
            //1、已上门订单，后台不能直接改派
            if (order.getStatus() >= OrderStatusConsts.WORK_STATUS_VISIT) {
                return OperatePermissionVO.fail("订单已上门，请使用工程师APP申请改派！");
            }
            String message = orderWorkRedistributeListBService.verifyWorkStatusForRedistribute(order, GlobalConsts.OPERATE_USER_TYPE_STAFF);
            if (StringUtils.isNotBlank(message)) {
                return OperatePermissionVO.fail(message);
            }

            //4. 改派时，工程师当前位置距离预约地址的距离 ≤ 100m
            // todo fubiao
            if (NumberUtil.isNotNullOrZero(order.getMasterId())) {
                ResponseDTO<ForeignEngineerLocationDRO> locationResponseDTO = engineerLocationRemoteService.getLocationByEngineerId(order.getMasterId());
                logger.info("获取工程师位置 入参：{} 出参：{}", order.getMasterId(), JSON.toJSONString(locationResponseDTO));
                if (locationResponseDTO.isSuccess()) {
                    if (Objects.nonNull(locationResponseDTO.getData())
                            && NumberUtil.isNotNullOrZero(locationResponseDTO.getData().getLatitude())
                            && NumberUtil.isNotNullOrZero(locationResponseDTO.getData().getLongitude())) {
                        ForeignEngineerLocationDRO location = locationResponseDTO.getData();
                        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
                        double distance = MapUtils.getDistance(orderDetail.getLatitude(), orderDetail.getLongitude(), location.getLatitude().doubleValue(), location.getLongitude().doubleValue());
                        if (distance <= 100) {
                            return OperatePermissionVO.fail("工程师已在附近，请使用工程师APP申请改派！");
                        }
                    }
                }
            }

        } catch (OmsBaseException e) {
            return OperatePermissionVO.fail(e.getMessage());
        }
        return this.distributePermission(order);
    }

    /**
     * 强制派单操作权限
     */
    private OperatePermissionVO forceDistributePermission(OrderWork order) {

        // 结果：已分单 - 进行中，可操作
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ASSIGN,OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT);

        // 是否网格化派单
        boolean isGrid = zsDistributeWorkBService.isGridDistribute(order);
        if (isGrid){
            supportStatusList.add(OrderStatusConsts.WORK_STATUS_CONFIRM);
        } else {
            // 服务商派单不支持强制派单
            return OperatePermissionVO.fail("服务商派单不支持强制派单");
        }

        // 返修单不支持强制派单
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REWORK)){
            return OperatePermissionVO.fail("返修单不支持强制派单");
        }

        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());

        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("工单未确认或未分单或已取消或已完成，不可操作");
        }

        // 挂起状态，不可操作
        if (Objects.equals(order.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            return OperatePermissionVO.fail("挂起状态，不可操作");
        }

        // C端订单，必须有预约时间，才可操作
        if (order.getDutyTime() == null && Objects.equals(order.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            return OperatePermissionVO.fail("请先确定预约时间，再派单");
        }

        if (this.isWaitPrePay(order)) {
            return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
        if (StringUtils.isBlank(orderDetail.getContactName())) {
            return OperatePermissionVO.fail("工单联系人姓名不规范，请调整后派单");
        }

        // 会员单，工程师审核后不能派单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        if (Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            return OperatePermissionVO.fail("工程师抢单中，此时此时不可操作强制派单");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 更改分配操作权限
     * @param order
     * @return
     */
    private OperatePermissionVO changeAssignmentPermission(OrderWork order) {

        // 只允许新单进抢单池
        if (!Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("返修单/退款单不可更改分配");
        }

        // 只有啄木鸟平台参与抢单
        if (!Objects.equals(order.getPlatWork(), com.zmn.consts.GlobalConsts.PLAT_MARK_ZMN)) {
            return OperatePermissionVO.fail("仅允许啄木鸟工单进抢单池");
        }

        // 结果：已分单 - 进行中，可操作
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_ASSIGN);

        // 是否网格化派单
        boolean isGrid = zsDistributeWorkBService.isGridDistribute(order);
        if (isGrid){
            supportStatusList.add(OrderStatusConsts.WORK_STATUS_CONFIRM);
        }

        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());

        if (!statusSupport) {
            return OperatePermissionVO.fail("不是已确认或已分单状态");
        }

        if (!resultStatusSupport) {
            return OperatePermissionVO.fail("不是进行中状态");
        }

        // 已派单过的，不需要处理
        if (order.getStatus() >= OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            return OperatePermissionVO.fail("已派单过");
        }

        // 挂起状态，不可操作
        if (Objects.equals(order.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            return OperatePermissionVO.fail("挂起状态，不可操作");
        }

        // C端订单，必须有预约时间，才可操作
        if (order.getDutyTime() == null && Objects.equals(order.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
            return OperatePermissionVO.fail("请先确定预约时间，再派单");
        }

        if (this.isWaitPrePay(order)) {
            return OperatePermissionVO.fail("用户正在支付预付款，请稍后");
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(order.getOrderId());
        if (StringUtils.isBlank(orderDetail.getContactName())) {
            return OperatePermissionVO.fail("工单联系人姓名不规范，请调整后派单");
        }

        // 会员单，工程师审核后不能派单
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        // 取消跟单状态
        OperatePermissionVO operatePermissionVO = workTrackBService.getOperatePermissionByTrack(order.getOrderId(), order.getWorkId());
        if (Objects.equals(operatePermissionVO.getCanOperate(), false)) {
            return operatePermissionVO;
        }

        // 判断抢单配置
        if (!Objects.equals(order.getGrabType(), GlobalConsts.YES)) {
            try {
                orderWorkGrabBService.grabConfig(order);
            } catch (Exception e) {
                return OperatePermissionVO.fail(e.getMessage());
            }
        }

        // 判断无网格抢单
        List<OrderTag> orderTagList = orderTagService.listOrderTagByOrderIdAndTagId(order.getOrderId(),
                OrderTagConsts.TAG_ID_NON_GRID);
        if (CollectionUtil.isNotNullOrEmpty(orderTagList)) {
            return OperatePermissionVO.fail("无网格订单，无法操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 确认操作权限
     */
    private OperatePermissionVO confirmPermission(OrderWork order) {

        // 赔偿单不可操作
        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("赔偿单不可操作");
        }

        // 结果：已录入 - 进行中，可操作
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_INPUT);
        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);

        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        boolean statusSupport = supportStatusList.contains(order.getStatus());

        if (!resultStatusSupport || !statusSupport) {
            return OperatePermissionVO.fail("工单已确认或已取消，不可操作");
        }

        boolean waitingChannelPrepay = Objects.equals(order.getDisableDiscard(), GlobalConsts.YES);
        if (waitingChannelPrepay) {
            return OperatePermissionVO.fail("工单正在等待渠道支付中，不可操作");
        }

        // 当订单“业务线&产品组&前后台产品分类（一级和二级）”为空时，不能确认，包括：自动确认、人工确认
        if (NumberUtil.isNullOrZero(order.getBizLine())
                || NumberUtil.isNullOrZero(order.getServProductGroupId())
                || NumberUtil.isNullOrZero(order.getCategId())
                || NumberUtil.isNullOrZero(order.getShowCategId())) {
            return OperatePermissionVO.fail("工单无业务线、产品组、前后台产品分类，不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 收款未支付检查
     *
     * @param order
     * @param operatorType
     * @param operatorId
     * @return
     */
    private OperatePermissionVO collectionNotPayCheck(OrderWork order, Integer type, Integer operatorType, Long operatorId) {
        // 不是子公司不检查
        boolean subCompanyStaff = isSubCompanyStaff(operatorType, operatorId);
        return this.collectionNotPayCheck(order,type,subCompanyStaff);
    }

    /**
     * 收款未支付检查
     *
     * @param order
     * @param type
     * @param subCompanyStaff
     * @return
     */
    private OperatePermissionVO collectionNotPayCheck(OrderWork order, Integer type, boolean subCompanyStaff) {
        if (!subCompanyStaff) {
            return OperatePermissionVO.success();
        }
        // 有：工程师收款未支付、子公司待收款 跟单
        List<TrackWorkDRO> noPayTrackList = this.getNoPayTrackList(order.getOrderId(), order.getWorkId());
        if (CollectionUtil.isNullOrEmpty(noPayTrackList)) {
            return OperatePermissionVO.success();
        }
        boolean isComplete = Objects.equals(type, OrderConsts.ORDER_OP_TYPE_COMPLETE);
        if (isComplete) {
            Integer noPayAmount = noPayTrackList.stream().filter(e -> Objects.nonNull(e.getAmount())).mapToInt(TrackWorkDRO::getAmount).sum();
            if (order.getTotalAmount() != null && noPayAmount > order.getTotalAmount()) {
                return OperatePermissionVO.fail(String.format("订单收入不能小于%s元！", MoneyUtil.parseToYuanStr(noPayAmount)));
            }
        } else {
            List<String> trackNameList = new ArrayList<>();
            for (TrackWorkDRO dro : noPayTrackList) {
                trackNameList.add(dro.getTrackContent());
            }
            return OperatePermissionVO.fail(String.format("%s，不可操作", StringUtils.join(trackNameList, ",")));
        }
        return OperatePermissionVO.success();
    }

    /**
     * 订单是否等待支付
     *
     * @param order
     * @return
     */
    @Override
    public boolean isWaitPrePay(OrderWork order) {
        return orderWorkBService.isWaitPrePay(order);
    }

    @Override
    public OperatePermissionVO requireOrderChannelAttachment(OrderAttachmentQuery orderAttachmentQuery) {
        OrderWorkAttachmentVO orderWorkAttachmentVO = orderAttachmentBService.getOrderAttachmentByQuery(orderAttachmentQuery);
        if (CollectionUtils.isEmpty(orderWorkAttachmentVO.getPictureList()) && CollectionUtils.isEmpty(orderWorkAttachmentVO.getServiceVideoList())) {
            return OperatePermissionVO.success();
        }


        // 照片检查
        if (CollectionUtils.isNotEmpty(orderWorkAttachmentVO.getPictureList())) {
            logger.info("查询必传照片,orderWorkAttachmentVO:{}",orderWorkAttachmentVO.getPictureList());
            for (OrderWorkAttachmentDetailVO orderWorkAttachmentDetailVO : orderWorkAttachmentVO.getPictureList()) {
                if (Objects.equals(orderWorkAttachmentDetailVO.getRequiredFlag(), GlobalConsts.YES) && StringUtils.isBlank(orderWorkAttachmentDetailVO.getSrc())) {
                    if (orderWorkAttachmentDetailVO.getOrderDetailShow()){
                        logger.info("您有必传照片未上传，请上传 orderAttachmentQuery={} orderWorkAttachmentDetailVO={}", JSON.toJSONString(orderAttachmentQuery), JSON.toJSONString(orderWorkAttachmentDetailVO));
                        return OperatePermissionVO.fail("您有必传照片未上传，请上传");
                    }
                }
            }
        }

        // 视频检查
        if (CollectionUtils.isNotEmpty(orderWorkAttachmentVO.getServiceVideoList())) {
            boolean hasBlankSrc = orderWorkAttachmentVO.getServiceVideoList().stream().filter(e -> Objects.equals(e.getRequiredFlag(), GlobalConsts.YES)
                    && StringUtils.isBlank(e.getSrc())).findAny().isPresent();
            if (hasBlankSrc) {
                return OperatePermissionVO.fail("您有必传视频未上传，请上传");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 一键提醒
     *
     * @param remindDTO
     * @return
     */
    @Override
    public OperatePermissionVO oneClickReminderCheck(RemindDTO remindDTO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(remindDTO.getOrderId(), remindDTO.getWorkId());
        if (Objects.equals(remindDTO.getType(), GlobalConsts.YES)) {
            // 联系用户
            if (!(Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) ||
                    Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK))) {
                return OperatePermissionVO.fail("工单类型不是新单或返修单");
            }
            if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
                return OperatePermissionVO.fail("工单未派单工程师，不可操作！！！");
            }
        } else {
            // 催单
            // return reminderPermission(orderWork);
        }
        return OperatePermissionVO.success();
    }

    /**
     * 修改工单照片权限
     *
     * @param orderWork
     * @return
     */
    public OperatePermissionVO photoPermission(OrderWork orderWork) {

        // 1、退款单，不可操作
        if (Objects.equals(OrderConsts.ORDER_TYPE_REFUND, orderWork.getType())) {
            return OperatePermissionVO.fail("退款单，不可操作");
        }

        // 1、赔偿单，不可操作
        if (Objects.equals(OrderConsts.ORDER_TYPE_COMPENSATE, orderWork.getType())) {
            return OperatePermissionVO.fail("赔偿单，不可操作");
        }

        // 2、派单后，可操作
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            return OperatePermissionVO.fail("工单未派单，不可操作");
        }

        // 3、工单：未算账，可操作
//        if (Objects.equals(OrderStatusConsts.WORK_STATUS_ACCOUNT, orderWork.getStatus())) {
//            return OperatePermissionVO.fail("工单已算账，不可操作");
//        }

        return OperatePermissionVO.success();

    }

    /**
     * 签到操作
     *
     * @param order
     * @returns
     */
    public OperatePermissionVO signInPermission(OrderWork order) {
        //   1.1、仅针对：天猫无忧购渠道的特殊操作；
        //2、操作限制：
        //   2.1、已领单-进行中&天猫无忧购渠道&收到签到失败预警通知15分钟之内；
        //   2.2、 不可操作提示语：
        //  A：工单非天猫无忧购渠道，不可操作；
        //  B：工单未收到签到失败通知，不可操作；
        //  C：已超时，不可操作；
        if (!Objects.equals(OrderConsts.CHANNEL_ID_TMALL_WYG, order.getChannelId())) {
            return OperatePermissionVO.fail("工单非天猫无忧购渠道，不可操作");
        }

        OrderTmallExtendDTO dto = new OrderTmallExtendDTO();
        dto.setOrderId(order.getOrderId());
        dto.setSignInStatus(GlobalConsts.NO);
        OrderTmallExtend orderSign = orderTmallExtendBService.findSignInByTmallQuery(dto);
        if (orderSign == null) {
            return OperatePermissionVO.fail("工单未收到签到失败通知，不可操作");
        }

        if (Objects.equals(GlobalConsts.YES, orderSign.getSignInStatus())) {
            return OperatePermissionVO.fail("已成功签到，不可重复操作");
        }

        Date resultTime = order.getResultTime();
        List<Integer> supportResultStatusList = Lists
                .newArrayList(OrderStatusConsts.WORK_RESULT_DOING, OrderStatusConsts.WORK_RESULT_SUCCESS);
        boolean resultStatusSupport = supportResultStatusList.contains(order.getResultStatus());
        if (resultTime != null && !resultStatusSupport) {
            return OperatePermissionVO.fail("工单已取消不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 六折优惠操作权限
     *
     * @param order
     * @return
     */
    public OperatePermissionVO discountLevelOnePermission(OrderWork order) {

        // 服务完成不可操作
        if (Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE)) {
            return OperatePermissionVO.fail("工单服务完成,不可操作");
        }

        // 会员单，工程师审核后不能操作
        if (Objects.equals(order.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            OrderMember orderMember = orderMemberService.findMemberByKey(order.getOrderId());
            if (!Objects.isNull(orderMember)) {
                if (Objects.equals(orderMember.getReviewStatus(), OrderConsts.ORDER_MEMBER_REVIEW_STATUS_WAIT_PLAT) && Objects
                        .equals(orderMember.getReviewResult(), OrderConsts.ORDER_MEMBER_REVIEW_RESULT_DOING)) {
                    return OperatePermissionVO.fail("工单需后台延保复审,不可操作");
                }
                boolean reviewSuccess = orderMember.getReviewStatus() == OrderConsts.ORDER_MEMBER_REVIEW_STATUS_PLAT_SUCCESS;
                if (reviewSuccess) {
                    return OperatePermissionVO.fail("工单为审核通过的延保订单，无法操作");
                }
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 快递信息操作
     *
     * @param orderWork
     * @returns
     */
    public OperatePermissionVO orderPostPermission(OrderWork orderWork) {

        if (Objects.nonNull(orderWork.getCompleteTime()) || Objects.nonNull(orderWork.getCancelTime())) {
            return OperatePermissionVO.fail("工单已完成或已取消，不可操作");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 新机配件信息操作
     * @param orderWork
     * @return com.zmn.oms.model.vo.work.OperatePermissionVO
     * @author wangxiaokun
     */
    public OperatePermissionVO orderNewMachinePartPermission(OrderWork orderWork) {

        if (Objects.nonNull(orderWork.getServiceCompleteTime()) || Objects.nonNull(orderWork.getCancelTime())) {
            return OperatePermissionVO.fail("工单已服务完成或已取消，不可操作");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 非标信息权限
     *
     * @param orderWork
     * @return
     */
    public OperatePermissionVO nonstandardPermission(OrderWork orderWork) {

        // 当工单状态是：已上门/已完成/已收单/已算账，按钮可用，其余状态禁用
        List<Integer> supportStatusList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_COMPLETE,
                OrderStatusConsts.WORK_STATUS_CHECKOUT,OrderStatusConsts.WORK_STATUS_ACCOUNT);
        if(!supportStatusList.contains(orderWork.getStatus())){
            return OperatePermissionVO.fail("当前状态无法操作");
        }
        return OperatePermissionVO.success();

    }

    /**
     * 服务完成审核权限
     *
     * @param orderWork
     * @return
     */
    public OperatePermissionVO serviceCompleteReviewPermission(OrderWork orderWork) {

        if (OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE != orderWork.getStatus() || OrderStatusConsts.WORK_RESULT_DOING != orderWork.getResultStatus()) {
            return OperatePermissionVO.fail("工单还未服务完成，不可操作");
        }
        if (orderWork.getServiceCompleteReviewStatus() != OrderConsts.REVIEW_STATUS_DOING) {
            return OperatePermissionVO.fail("工单非服务完成待审核状态，不可操作");
        }
        if(orderWork.getBizType() != com.zmn.consts.GlobalConsts.BIZ_TYPE_F || orderWork.getType() != OrderConsts.ORDER_TYPE_NEW){
            return OperatePermissionVO.fail("仅F端新单可操作服务审核");
        }
        if(orderWork.getServiceCompleteReviewStatus() == GlobalConsts.YES){
            return OperatePermissionVO.fail("工单已审核，不可重复审核");
        }

        //  1.4、渠道设置了对应的审核部门员工才可操作 -- 不可操作提示语：对应部门员工才可操作
       /* ResponseDTO<ChannelDRO> channelResponseDTO = channelListRemoteService.getByChannelId(orderWork.getChannelId());
        if(channelResponseDTO.isSuccess() && channelResponseDTO.getData() != null) {
            ChannelDRO channelDRO = channelResponseDTO.getData();

            if(Objects.isNull(channelDRO.getPriceAuditDeptId())){
                return OperatePermissionVO.fail("您不是当前订单的审核部门，无法操作");
            }
        }*/

        return OperatePermissionVO.success();

    }

    /**
     * 特殊调整权限
     *
     * @param orderWork
     * @return
     */
    public OperatePermissionVO specialAdjustment(OrderWork orderWork) {

        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_ACCOUNT) {
            return OperatePermissionVO.fail("工单还未算账，不可操作");
        }
        if (!(Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW))) {
            return OperatePermissionVO.fail("工单非新单或退款单，不可操作");
        }
        if (Objects.equals(orderWork.getManageCompanyType(), com.zmn.base.plat.engine.common.constant.CompanyConsts.COMPANY_TYPE_SERVICE)) {
            return OperatePermissionVO.fail("工单为信息公司，不可操作");
        }

        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            if (DateUtil.getNow().after(DateUtil.addDays(orderWork.getAccountTime(), 3))) {
                return OperatePermissionVO.fail("订单已算账3天，不可操作");
            }
        } else if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            if (DateUtil.getNow().after(DateUtil.addDays(orderWork.getAccountTime(), 30))) {
                return OperatePermissionVO.fail("订单已算账30天，不可操作");
            }
        }

        List<OrderLog> orderLogs = orderLogBService.findOrderLogsByWorkId(orderWork.getWorkId());
        Optional<OrderLog> orderLog = orderLogs.stream().filter(log -> {
            return Objects.equals(log.getType(), OrderLogConsts.ORDER_LOG_TYPE_SPECIAL_ADJUSTMENT);
        }).findFirst();
        if (orderLog.isPresent()) {
            return OperatePermissionVO.fail("订单已操作过特殊调整，不可操作");
        }

        return OperatePermissionVO.success();

    }

    private OperatePermissionVO discountAndCouponPermission(OrderWork orderWork) {
        OperatePermissionVO discountPermission = this.discountPermission(orderWork);
        if (discountPermission.getCanOperate()) {
            return discountPermission;
        }
        OperatePermissionVO couponPermission = this.discountCouponPermission(orderWork);
        return couponPermission;
    }

    /**
     * 退款凭证
     * @param orderWork
     * @return
     */
    private OperatePermissionVO refundVoucherPermission(OrderWork orderWork){

        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            return OperatePermissionVO.fail("非退款单，不可操作");
        }

        if (Objects.nonNull(orderWork.getCancelTime())) {
            return OperatePermissionVO.fail("退款单已取消，不可操作");
        }

        OmsOrderReview omsOrderReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_REFUND);
        if (Objects.nonNull(omsOrderReview) && Objects.equals(omsOrderReview.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_FAIL)) {
            return OperatePermissionVO.fail("退款单审核失败，不可操作");
        }

        List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkIdsAndTradeType(orderWork.getOrderId(), Lists.newArrayList(orderWork.getWorkId()), PayConsts.PAY_TRADE_TYPE_REFUND);
        if (CollectionUtil.isNullOrEmpty(orderPays)) {
            return OperatePermissionVO.fail("没有退款记录，不可操作");
        }
        OrderPay orderPay = orderPays.get(0);

        if (Objects.equals(RefundTypeEnum.ORIGINAL_REFUND.getType(), orderPay.getRefundType())) {
            return OperatePermissionVO.fail("原路退回，不可操作");
        }

        if (Objects.equals(RefundTypeEnum.CASH_REFUND.getType(), orderPay.getPayTargetChannelId())) {
            return OperatePermissionVO.fail("现金退款，不可操作");
        }

        // 退款单未确认不可操作
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_CONFIRM) {
            return OperatePermissionVO.fail("退款单未确认，不可操作");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 工单分润
     * @param orderWork
     * @return
     */
    private OperatePermissionVO masterSharingPermission(OrderWork orderWork){

        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) && !Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            return OperatePermissionVO.fail("订单非新单或返修单，不可操作");
        }

        if (!Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_COMPLETE) && !Objects.equals(orderWork.getStatus(), OrderStatusConsts.WORK_STATUS_CHECKOUT)) {
            return OperatePermissionVO.fail("订单非已完成或已收单状态，不可操作");
        }

        if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {
            return OperatePermissionVO.fail("订单已弃单，不可操作");
        }

        // TODO liuying 多师傅状态数据修复
        List<OrderMaster> orderMasterList = orderMasterService.listMasterByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
        try {
            if (CollectionUtils.isNotEmpty(orderMasterList)) {
                if (orderMasterList.size() > 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.YES)) {
                    OrderWork updateOrderWork = new OrderWork();
                    updateOrderWork.setOrderId(orderWork.getOrderId());
                    updateOrderWork.setWorkId(orderWork.getWorkId());
                    updateOrderWork.setMultiMaster(GlobalConsts.YES);
                    updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                    updateOrderWork.setUpdateTime(DateUtil.getNow());
                    orderWorkService.saveMultiMaster(updateOrderWork);

                    orderWork.setMultiMaster(GlobalConsts.YES);
                } else if (orderMasterList.size() == 1 && !Objects.equals(orderWork.getMultiMaster(), GlobalConsts.NO)) {
                    OrderWork updateOrderWork = new OrderWork();
                    updateOrderWork.setOrderId(orderWork.getOrderId());
                    updateOrderWork.setWorkId(orderWork.getWorkId());
                    updateOrderWork.setMultiMaster(GlobalConsts.NO);
                    updateOrderWork.setUpdater(com.zmn.common.constant.GlobalConsts.getOperatorTypeName(com.zmn.common.constant.GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                    updateOrderWork.setUpdateTime(DateUtil.getNow());
                    orderWorkService.saveMultiMaster(updateOrderWork);

                    orderWork.setMultiMaster(GlobalConsts.NO);
                }
            }
        } catch (Exception ex){}

        if (Objects.equals(orderWork.getMultiMaster(), GlobalConsts.NO)) {
            return OperatePermissionVO.fail("订单非多工程师，不可操作");
        }

        return OperatePermissionVO.success();
    }

    private OperatePermissionVO reminderPermission(OrderWork order) {

        if (!(Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_DISTRIBUTE)
                || Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE)
                || Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_VISIT))
                || !Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("已派单、已领单、已上门且进行中可催单");
        }

        return OperatePermissionVO.success();
    }

    private OperatePermissionVO markPermission(OrderWork order) {
//        if (!(Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING) && Objects.isNull(order.getServiceCompleteTime()))) {
//            return OperatePermissionVO.fail("工单已取消或服务已完成，不能标记");
//        }
        if (!Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return OperatePermissionVO.fail("返修单和退款单，不能标记");
        }

        return OperatePermissionVO.success();
    }

    /**
     * 多次上门
     * @param order
     * @return
     */
    private OperatePermissionVO multipleVisitPermission(OrderWork order) {

        if (!Objects.equals(order.getStatus(), OrderStatusConsts.WORK_STATUS_VISIT) ||
                !Objects.equals(order.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return OperatePermissionVO.fail("工单未上门或已完成或已取消，不可申请");
        }

        if (Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_REFUND)
                || Objects.equals(order.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            return OperatePermissionVO.fail("退款单或赔偿单，不可申请");
        }

        if (NumberUtil.isNullOrZero(order.getProductId())) {
            return OperatePermissionVO.fail("工单无后台产品，请填写后台产品");
        }

        if (Objects.equals(order.getDutyStatus(), OrderDutyConsts.DUTY_STATUS_SUSPEND)) {
            return OperatePermissionVO.fail("工单已挂起，不可操作");
        }

        if (Objects.isNull(order.getDutyTime())) {
            return OperatePermissionVO.fail("工单预约失败，请填写预约时间");
        }

        List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterId(order.getOrderId(), order.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(orderVisitList)) {
            OrderVisit orderVisit = orderVisitList.get(0);
            if (Objects.equals(orderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY) ||
                    Objects.equals(orderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT)) {
                return OperatePermissionVO.fail("已存在再次上门申请，不可重复申请");
            }
        }

        return OperatePermissionVO.success();
    }

    /**
     * 临时小号
     * @param orderWork
     * @return
     */
    private OperatePermissionVO tempXnoPermission(OrderWork orderWork) {
        if (!(Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK))) {
            return OperatePermissionVO.fail("工单不是新单、返修单，不可操作");
        }
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
        if (com.zmn.account.common.utils.NumberUtil.isNullOrZero(orderDetail.getGridManageCompanyId()) && com.zmn.account.common.utils.NumberUtil.isNullOrZero(orderWork.getManageCompanyId())) {
            return OperatePermissionVO.fail("工单不存子公司，不可操作！");
        }
        return OperatePermissionVO.success();
    }

    /**
     * 获取待支付跟单
     *
     * @param orderId
     * @param workId
     * @return
     */
    private List<TrackWorkDRO> getNoPayTrackList(Long orderId, Long workId) {
        try {
            TrackWorkQueryDIO trackWorkQueryDIO = new TrackWorkQueryDIO();
            trackWorkQueryDIO.setOrderId(orderId);
            trackWorkQueryDIO.setWorkId(workId);
            trackWorkQueryDIO.setTrackContentIdList(Lists.newArrayList(TrackConfigConsts.TRACK_CONTENT_ID_COMPANY_MONEY,
                    TrackConfigConsts.TRACK_CONTENT_ID_ENGINEER_MONEY_NO_PAY));
            trackWorkQueryDIO.setTrackStatusList(Lists.newArrayList(TrackConsts.TRACK_STATUS_PENDING, TrackConsts.TRACK_STATUS_PROCESSING));
            logger.info("工单[{}]查询收款未支付的跟单 入参：{}", workId, JSON.toJSON(trackWorkQueryDIO));
            ResponseDTO<List<TrackWorkDRO>> responseDTO = trackWorkListRemoteService.listTrackWorkByQuery(trackWorkQueryDIO);
            logger.info("工单[{}]查询收款未支付的跟单 出参：{}", workId, JSON.toJSON(trackWorkQueryDIO));
            if (responseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
                return responseDTO.getData();
            }
        } catch (Exception ex) {
            logger.error("[{}]查询收款未支付跟单 异常：{}", workId, ex);
        }
        return Lists.newArrayList();
    }
}
